001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.geronimo.deployment.service;
019
020 import java.beans.PropertyEditorSupport;
021 import java.util.ArrayList;
022 import java.util.Collection;
023 import java.util.HashSet;
024 import java.util.Iterator;
025 import java.util.LinkedHashSet;
026 import java.util.List;
027 import java.util.Set;
028
029 import javax.xml.namespace.QName;
030
031 import org.apache.geronimo.common.DeploymentException;
032 import org.apache.geronimo.common.propertyeditor.PropertyEditorException;
033 import org.apache.geronimo.deployment.xbeans.ArtifactType;
034 import org.apache.geronimo.deployment.xbeans.ClassFilterType;
035 import org.apache.geronimo.deployment.xbeans.DependenciesType;
036 import org.apache.geronimo.deployment.xbeans.EnvironmentDocument;
037 import org.apache.geronimo.deployment.xbeans.EnvironmentType;
038 import org.apache.geronimo.deployment.xbeans.ImportType;
039 import org.apache.geronimo.deployment.xbeans.DependencyType;
040 import org.apache.geronimo.kernel.repository.Artifact;
041 import org.apache.geronimo.kernel.repository.Dependency;
042 import org.apache.geronimo.kernel.repository.Environment;
043 import org.apache.xmlbeans.XmlException;
044 import org.apache.xmlbeans.XmlObject;
045 import org.apache.xmlbeans.XmlOptions;
046
047 /**
048 * @version $Rev: 476049 $ $Date: 2006-11-16 23:35:17 -0500 (Thu, 16 Nov 2006) $
049 */
050 public class EnvironmentBuilder extends PropertyEditorSupport implements XmlAttributeBuilder {
051 private final static QName QNAME = EnvironmentDocument.type.getDocumentElementName();
052 private final static String NAMESPACE = QNAME.getNamespaceURI();
053
054 public static Environment buildEnvironment(EnvironmentType environmentType) {
055 Environment environment = new Environment();
056 if (environmentType != null) {
057 if (environmentType.isSetModuleId()) {
058 environment.setConfigId(toArtifact(environmentType.getModuleId(), null));
059 }
060
061 if (environmentType.isSetDependencies()) {
062 DependencyType[] dependencyArray = environmentType.getDependencies().getDependencyArray();
063 LinkedHashSet dependencies = toDependencies(dependencyArray);
064 environment.setDependencies(dependencies);
065 }
066 environment.setInverseClassLoading(environmentType.isSetInverseClassloading());
067 environment.setSuppressDefaultEnvironment(environmentType.isSetSuppressDefaultEnvironment());
068 environment.setHiddenClasses(toFilters(environmentType.getHiddenClasses()));
069 environment.setNonOverrideableClasses(toFilters(environmentType.getNonOverridableClasses()));
070 }
071
072 return environment;
073 }
074
075 public static void mergeEnvironments(Environment environment, Environment additionalEnvironment) {
076 if (additionalEnvironment != null) {
077 //TODO merge configIds??
078 if (environment.getConfigId() == null) {
079 environment.setConfigId(additionalEnvironment.getConfigId());
080 }
081 environment.addDependencies(additionalEnvironment.getDependencies());
082 environment.setInverseClassLoading(environment.isInverseClassLoading() || additionalEnvironment.isInverseClassLoading());
083 environment.setSuppressDefaultEnvironment(environment.isSuppressDefaultEnvironment() || additionalEnvironment.isSuppressDefaultEnvironment());
084 environment.addHiddenClasses(additionalEnvironment.getHiddenClasses());
085 environment.addNonOverrideableClasses(additionalEnvironment.getNonOverrideableClasses());
086 }
087 }
088
089 public static Environment buildEnvironment(EnvironmentType environmentType, Environment defaultEnvironment) {
090 Environment environment = buildEnvironment(environmentType);
091 if (!environment.isSuppressDefaultEnvironment()) {
092 mergeEnvironments(environment, defaultEnvironment);
093 }
094 return environment;
095 }
096
097 public static EnvironmentType buildEnvironmentType(Environment environment) {
098 EnvironmentType environmentType = EnvironmentType.Factory.newInstance();
099 if (environment.getConfigId() != null) {
100 ArtifactType configId = toArtifactType(environment.getConfigId());
101 environmentType.setModuleId(configId);
102 }
103
104 List dependencies = toDependencyTypes(environment.getDependencies());
105 DependencyType[] dependencyTypes = (DependencyType[]) dependencies.toArray(new DependencyType[dependencies.size()]);
106 DependenciesType dependenciesType = environmentType.addNewDependencies();
107 dependenciesType.setDependencyArray(dependencyTypes);
108 if (environment.isInverseClassLoading()) {
109 environmentType.addNewInverseClassloading();
110 }
111 if (environment.isSuppressDefaultEnvironment()) {
112 environmentType.addNewSuppressDefaultEnvironment();
113 }
114 environmentType.setHiddenClasses(toFilterType(environment.getHiddenClasses()));
115 environmentType.setNonOverridableClasses(toFilterType(environment.getNonOverrideableClasses()));
116 return environmentType;
117 }
118
119 private static ClassFilterType toFilterType(Set filters) {
120 String[] classFilters = (String[]) filters.toArray(new String[filters.size()]);
121 ClassFilterType classFilter = ClassFilterType.Factory.newInstance();
122 classFilter.setFilterArray(classFilters);
123 return classFilter;
124 }
125
126 private static List toDependencyTypes(Collection artifacts) {
127 List dependencies = new ArrayList();
128 for (Iterator iterator = artifacts.iterator(); iterator.hasNext();) {
129 Dependency dependency = (Dependency) iterator.next();
130 ArtifactType artifactType = toDependencyType(dependency);
131 dependencies.add(artifactType);
132 }
133 return dependencies;
134 }
135
136 private static ArtifactType toArtifactType(Artifact artifact) {
137 ArtifactType artifactType = ArtifactType.Factory.newInstance();
138 fillArtifactType(artifact, artifactType);
139 return artifactType;
140 }
141
142 private static void fillArtifactType(Artifact artifact, ArtifactType artifactType) {
143 if (artifact.getGroupId() != null) {
144 artifactType.setGroupId(artifact.getGroupId());
145 }
146 if (artifact.getArtifactId() != null) {
147 artifactType.setArtifactId(artifact.getArtifactId());
148 }
149 if (artifact.getVersion() != null) {
150 artifactType.setVersion(artifact.getVersion().toString());
151 }
152 if (artifact.getType() != null) {
153 artifactType.setType(artifact.getType());
154 }
155 }
156
157 private static DependencyType toDependencyType(Dependency dependency) {
158 DependencyType dependencyType = DependencyType.Factory.newInstance();
159 fillArtifactType(dependency.getArtifact(), dependencyType);
160
161 org.apache.geronimo.kernel.repository.ImportType importType = dependency.getImportType();
162 if (importType == org.apache.geronimo.kernel.repository.ImportType.CLASSES) {
163 dependencyType.setImport(ImportType.CLASSES);
164 } else if (importType == org.apache.geronimo.kernel.repository.ImportType.SERVICES) {
165 dependencyType.setImport(ImportType.SERVICES);
166 }
167
168 return dependencyType;
169 }
170
171 private static Set toFilters(ClassFilterType filterType) {
172 Set filters = new HashSet();
173 if (filterType != null) {
174 String[] filterArray = filterType.getFilterArray();
175 for (int i = 0; i < filterArray.length; i++) {
176 String filter = filterArray[i].trim();
177 filters.add(filter);
178 }
179 }
180 return filters;
181 }
182
183 //package level for testing
184 static LinkedHashSet toArtifacts(ArtifactType[] artifactTypes) {
185 LinkedHashSet artifacts = new LinkedHashSet();
186 for (int i = 0; i < artifactTypes.length; i++) {
187 ArtifactType artifactType = artifactTypes[i];
188 Artifact artifact = toArtifact(artifactType, "jar");
189 artifacts.add(artifact);
190 }
191 return artifacts;
192 }
193
194 private static LinkedHashSet toDependencies(DependencyType[] dependencyArray) {
195 LinkedHashSet dependencies = new LinkedHashSet();
196 for (int i = 0; i < dependencyArray.length; i++) {
197 DependencyType artifactType = dependencyArray[i];
198 Dependency dependency = toDependency(artifactType);
199 dependencies.add(dependency);
200 }
201 return dependencies;
202 }
203
204 private static Dependency toDependency(DependencyType dependencyType) {
205 Artifact artifact = toArtifact(dependencyType, null);
206 if (ImportType.CLASSES.equals(dependencyType.getImport())) {
207 return new Dependency(artifact, org.apache.geronimo.kernel.repository.ImportType.CLASSES);
208 } else if (ImportType.SERVICES.equals(dependencyType.getImport())) {
209 return new Dependency(artifact, org.apache.geronimo.kernel.repository.ImportType.SERVICES);
210 } else if (dependencyType.getImport() == null) {
211 return new Dependency(artifact, org.apache.geronimo.kernel.repository.ImportType.ALL);
212 } else {
213 throw new IllegalArgumentException("Unknown import type: " + dependencyType.getImport());
214 }
215 }
216
217 private static Artifact toArtifact(ArtifactType artifactType, String defaultType) {
218 String groupId = artifactType.isSetGroupId() ? trim(artifactType.getGroupId()) : null;
219 String type = artifactType.isSetType() ? trim(artifactType.getType()) : defaultType;
220 String artifactId = trim(artifactType.getArtifactId());
221 String version = artifactType.isSetVersion() ? trim(artifactType.getVersion()) : null;
222 return new Artifact(groupId, artifactId, version, type);
223 }
224
225 private static String trim(String string) {
226 if (string == null || string.length() == 0) {
227 return null;
228 }
229 return string.trim();
230 }
231
232
233 public String getNamespace() {
234 return NAMESPACE;
235 }
236
237 public Object getValue(XmlObject xmlObject, String type, ClassLoader cl) throws DeploymentException {
238
239 EnvironmentType environmentType;
240 if (xmlObject instanceof EnvironmentType) {
241 environmentType = (EnvironmentType) xmlObject;
242 } else {
243 environmentType = (EnvironmentType) xmlObject.copy().changeType(EnvironmentType.type);
244 }
245 try {
246 XmlOptions xmlOptions = new XmlOptions();
247 xmlOptions.setLoadLineNumbers();
248 Collection errors = new ArrayList();
249 xmlOptions.setErrorListener(errors);
250 if (!environmentType.validate(xmlOptions)) {
251 throw new XmlException("Invalid deployment descriptor: " + errors + "\nDescriptor: " + environmentType.toString(), null, errors);
252 }
253 } catch (XmlException e) {
254 throw new DeploymentException(e);
255 }
256
257 return buildEnvironment(environmentType);
258 }
259
260 public String getAsText() {
261 Environment environment = (Environment) getValue();
262 EnvironmentType environmentType = buildEnvironmentType(environment);
263 XmlOptions xmlOptions = new XmlOptions();
264 xmlOptions.setSaveSyntheticDocumentElement(QNAME);
265 xmlOptions.setSavePrettyPrint();
266 return environmentType.xmlText(xmlOptions);
267 }
268
269 public void setAsText(String text) {
270 try {
271 EnvironmentDocument environmentDocument = EnvironmentDocument.Factory.parse(text);
272 EnvironmentType environmentType = environmentDocument.getEnvironment();
273 Environment environment = (Environment) getValue(environmentType, null, null);
274 setValue(environment);
275
276 } catch (XmlException e) {
277 throw new PropertyEditorException(e);
278 } catch (DeploymentException e) {
279 throw new PropertyEditorException(e);
280 }
281 }
282
283
284 //This is added by hand to the xmlAttributeBuilders since it is needed to bootstrap the ServiceConfigBuilder.
285 }