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