1/* 2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.xml.internal.ws.policy; 27 28import com.sun.xml.internal.ws.policy.privateutil.PolicyUtils; 29import com.sun.xml.internal.ws.policy.sourcemodel.wspolicy.NamespaceVersion; 30import java.util.ArrayList; 31import java.util.Collection; 32import java.util.LinkedList; 33 34/** 35 * Merge policies and return the effective policy. 36 * 37 * WS-PolicyAttachment defines a merge algorithm for WSDL 1.1 policy attachments. 38 */ 39public final class PolicyMerger { 40 private static final PolicyMerger merger = new PolicyMerger(); 41 42 /** 43 * This private constructor is to avoid direct class instantiation from outsied of the package 44 */ 45 private PolicyMerger() { 46 // nothing to instantiate 47 } 48 49 /** 50 * Factory method for obtaining thread-safe policy merger instance. 51 * 52 * @return policy merger instance. 53 */ 54 public static PolicyMerger getMerger() { 55 return merger; 56 } 57 58 /** 59 * Takes collection of policies and merges them into a single policy using algorithm described in 60 * WS-PolicyAttachment specification. None of the original policies in the collection are modified in 61 * any way. 62 * 63 * The newly created policy has an ID that is a concatentation of all merged policy IDs. 64 * 65 * @param policies collection of policies to be merged. The collection must not contain '{@code null}' elements! 66 * @return merged policy containing combination of policy alternatives stored in all input policies. 67 * If provided collection of policies is {@code null} or empty, returns {@code null}. If provided 68 * collection of policies contains only single policy, the policy is returned. 69 */ 70 public Policy merge(final Collection<Policy> policies) { 71 if (policies == null || policies.isEmpty()) { 72 return null; 73 } else if (policies.size() == 1) { 74 return policies.iterator().next(); 75 } 76 77 final Collection<Collection<AssertionSet>> alternativeSets = new LinkedList<Collection<AssertionSet>>(); 78 final StringBuilder id = new StringBuilder(); 79 NamespaceVersion mergedVersion = policies.iterator().next().getNamespaceVersion(); 80 for (Policy policy : policies) { 81 alternativeSets.add(policy.getContent()); 82 if (mergedVersion.compareTo(policy.getNamespaceVersion()) < 0) { 83 mergedVersion = policy.getNamespaceVersion(); 84 } 85 final String policyId = policy.getId(); 86 if (policyId != null) { 87 if (id.length() > 0) { 88 id.append('-'); 89 } 90 id.append(policyId); 91 } 92 } 93 94 final Collection<Collection<AssertionSet>> combinedAlternatives = PolicyUtils.Collections.combine(null, alternativeSets, false); 95 96 if (combinedAlternatives == null || combinedAlternatives.isEmpty()) { 97 return Policy.createNullPolicy(mergedVersion, null, id.length() == 0 ? null : id.toString()); 98 } else { 99 final Collection<AssertionSet> mergedSetList = new ArrayList<AssertionSet>(combinedAlternatives.size()); 100 for (Collection<AssertionSet> toBeMerged : combinedAlternatives) { 101 mergedSetList.add(AssertionSet.createMergedAssertionSet(toBeMerged)); 102 } 103 return Policy.createPolicy(mergedVersion, null, id.length() == 0 ? null : id.toString(), mergedSetList); 104 } 105 } 106} 107