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.jaxws.builder;
019    
020    import java.io.File;
021    import java.io.OutputStream;
022    import java.lang.reflect.Method;
023    import java.net.MalformedURLException;
024    import java.net.URL;
025    import java.net.URLClassLoader;
026    import java.util.ArrayList;
027    import java.util.Collection;
028    import java.util.SortedSet;
029    
030    import org.apache.commons.logging.Log;
031    import org.apache.commons.logging.LogFactory;
032    import org.apache.geronimo.kernel.repository.Artifact;
033    import org.apache.geronimo.kernel.repository.ListableRepository;
034    import org.apache.geronimo.kernel.repository.Repository;
035    import org.apache.geronimo.kernel.repository.Version;
036    
037    public class JAXWSTools {
038    
039        private static final Log LOG = LogFactory.getLog(JAXWSTools.class);
040            
041        private final static String [][] LIBS =
042        { 
043            { "org.apache.axis2", "axis2-jaxws-api" },
044            { "org.apache.geronimo.specs", "geronimo-saaj_1.3_spec" },
045            { "javax.xml.bind",   "jaxb-api" },
046            { "com.sun.xml.bind", "jaxb-impl" },
047            { "com.sun.xml.bind", "jaxb-xjc" },
048            { "com.sun.xml.ws",   "jaxws-tools" },
049            { "com.sun.xml.ws",   "jaxws-rt" },
050            { "org.apache.geronimo.javamail", "geronimo-javamail_1.4_mail"},
051            { "org.apache.geronimo.specs",    "geronimo-activation_1.1_spec"},
052            { "org.apache.geronimo.specs",    "geronimo-annotation_1.0_spec"},
053            { "org.apache.geronimo.specs",    "geronimo-ws-metadata_2.0_spec"},
054            { "org.apache.geronimo.specs",    "geronimo-ejb_3.0_spec"},
055            { "org.apache.geronimo.specs",    "geronimo-interceptor_3.0_spec"},
056            { "org.apache.geronimo.specs",    "geronimo-stax-api_1.0_spec"},
057            { "org.apache.geronimo.specs",    "geronimo-jpa_3.0_spec"},
058            { "org.apache.geronimo.specs",    "geronimo-j2ee-connector_1.5_spec"},
059            { "org.apache.geronimo.specs",    "geronimo-jms_1.1_spec"},
060            { "org.apache.geronimo.specs",    "geronimo-jta_1.1_spec"},
061            { "org.apache.geronimo.specs",    "geronimo-j2ee-management_1.1_spec"},
062        };
063        
064        private final static Artifact SUN_SAAJ_IMPL_ARTIFACT = new Artifact("com.sun.xml.messaging.saaj","saaj-impl", (Version)null, "jar");
065        private final static Artifact AXIS2_SAAJ_IMPL_ARTIFACT = new Artifact("org.apache.axis2","axis2-saaj", (Version)null, "jar");
066        private final static String TOOLS = "tools.jar";
067    
068        private Artifact saajImpl;
069        private boolean overrideContextClassLoader;
070        
071        public JAXWSTools() {
072        }
073        
074        public void setUseSunSAAJ() {
075            this.saajImpl = SUN_SAAJ_IMPL_ARTIFACT;
076        }
077        
078        public void setUseAxis2SAAJ() {
079            this.saajImpl = AXIS2_SAAJ_IMPL_ARTIFACT;
080        }
081        
082        public void setOverrideContextClassLoader(boolean overrideContextClassLoader) {
083            this.overrideContextClassLoader = overrideContextClassLoader;
084        }
085        
086        public boolean getOverrideContextClassLoader() {
087            return this.overrideContextClassLoader;
088        }
089           
090        public static URL[] toURL(File[] jars) throws MalformedURLException {
091            URL [] urls = new URL[jars.length];
092            for (int i = 0; i < jars.length; i++) {
093                urls[i] = jars[i].toURL();
094            }
095            return urls;
096        }
097        
098        public static String toString(File [] jars) {
099            StringBuffer buf = new StringBuffer();
100            for (int i = 0; i < jars.length; i++) {
101                buf.append(jars[i].getAbsolutePath());
102                if (i+1 < jars.length) {
103                    buf.append(File.pathSeparatorChar);
104                }
105            }
106            return buf.toString();
107        }
108        
109        public File[] getClasspath(Collection<? extends Repository> repositories) throws Exception {
110            ArrayList<File> jars = new ArrayList<File>();
111            for (String[] lib : LIBS) {
112                Artifact artifact = new Artifact(lib[0], lib[1], (Version)null, "jar");
113                jars.add(getLocation(repositories, artifact));
114            }
115            if (this.saajImpl != null) {
116                jars.add(getLocation(repositories, this.saajImpl));
117            }
118            addToolsJarLocation(jars);
119            
120            return jars.toArray(new File[jars.size()]);
121        }
122           
123        private static File getLocation(Collection<? extends Repository> repositories, Artifact artifactQuery) throws Exception {
124            File file = null;
125            
126            for (Repository arepository : repositories) {
127                if (arepository instanceof ListableRepository) {
128                    ListableRepository repository = (ListableRepository) arepository;
129                    SortedSet artifactSet = repository.list(artifactQuery);
130                    // if we have exactly one artifact found
131                    if (artifactSet.size() == 1) {
132                        file = repository.getLocation((Artifact) artifactSet.first());
133                        return file.getAbsoluteFile();
134                    } else if (artifactSet.size() > 1) {// if we have more than 1 artifacts found use the latest one.
135                        file = repository.getLocation((Artifact) artifactSet.last());
136                        return file.getAbsoluteFile();
137                    }
138                }
139            }
140            
141            throw new Exception("Missing artifact in repositories: " + artifactQuery.toString());
142        }
143        
144        private static void addToolsJarLocation(ArrayList<File> jars) {
145            //create a new File then check exists()
146            String jreHomePath = System.getProperty("java.home");
147            String javaHomePath = "";
148            int jreHomePathLength = jreHomePath.length();
149            if (jreHomePathLength > 0) {
150                int i = jreHomePath.substring(0, jreHomePathLength -1).lastIndexOf(java.io.File.separator);
151                javaHomePath = jreHomePath.substring(0, i);
152            }
153            File jdkhomelib = new File(javaHomePath, "lib");
154            if (!jdkhomelib.exists()) {
155                LOG.warn("Missing " + jdkhomelib.getAbsolutePath()
156                        + ". This may be required for wsgen to run. ");
157            }
158            else {
159                File tools = new File(jdkhomelib, TOOLS);
160                if (!tools.exists()) {
161                    LOG.warn("Missing tools.jar in" + jdkhomelib.getAbsolutePath()
162                            + ". This may be required for wsgen to run. ");
163                } else {
164                    jars.add(tools.getAbsoluteFile());
165                }               
166            }
167        }
168                               
169        public boolean invokeWsgen(URL[] jars, OutputStream os, String[] arguments) throws Exception {
170            return invoke("wsgen", jars, os, arguments);
171        
172        }
173        public boolean invokeWsimport(URL[] jars, OutputStream os, String[] arguments) throws Exception {
174            return invoke("wsimport", jars, os, arguments);
175        }
176        
177        private boolean invoke(String toolName, URL[] jars, OutputStream os, String[] arguments) throws Exception {        
178            URLClassLoader loader = new URLClassLoader(jars, ClassLoader.getSystemClassLoader());
179            if (this.overrideContextClassLoader) {
180                ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
181                Thread.currentThread().setContextClassLoader(loader);
182                try {
183                    return invoke(toolName, loader, os, arguments);
184                } finally {
185                    Thread.currentThread().setContextClassLoader(oldClassLoader);
186                }            
187            } else {
188                return invoke(toolName, loader, os, arguments);
189            }
190        }
191        
192        private boolean invoke(String toolName, ClassLoader loader, OutputStream os, String[] arguments) throws Exception {
193            LOG.debug("Invoking " + toolName);
194            Class clazz = loader.loadClass("com.sun.tools.ws.spi.WSToolsObjectFactory");
195            Method method = clazz.getMethod("newInstance");
196            Object factory = method.invoke(null);
197            Method method2 = clazz.getMethod(toolName, OutputStream.class, String[].class);
198            
199            Boolean result = (Boolean) method2.invoke(factory, os, arguments);
200            
201            return result;
202        }
203        
204    }