View Javadoc

1   /*
2    * Copyright 2003,2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.apache.pluto.portalImpl;
18  
19  import java.io.BufferedReader;
20  import java.io.File;
21  import java.io.FileInputStream;
22  import java.io.FileOutputStream;
23  import java.io.FileWriter;
24  import java.io.IOException;
25  import java.io.InputStream;
26  import java.io.InputStreamReader;
27  import java.io.RandomAccessFile;
28  import java.io.Reader;
29  import java.io.StreamTokenizer;
30  import java.util.Collection;
31  import java.util.Enumeration;
32  import java.util.Iterator;
33  import java.util.Locale;
34  import java.util.StringTokenizer;
35  import java.util.Vector;
36  import java.util.jar.JarEntry;
37  import java.util.jar.JarFile;
38  
39  import org.apache.pluto.om.common.Parameter;
40  import org.apache.pluto.om.common.ParameterCtrl;
41  import org.apache.pluto.om.common.ParameterSet;
42  import org.apache.pluto.om.common.ParameterSetCtrl;
43  import org.apache.pluto.om.common.SecurityRoleRef;
44  import org.apache.pluto.om.common.SecurityRoleRefSet;
45  import org.apache.pluto.om.common.SecurityRoleRefSetCtrl;
46  import org.apache.pluto.om.common.SecurityRoleSet;
47  import org.apache.pluto.om.portlet.PortletDefinition;
48  import org.apache.pluto.om.servlet.ServletDefinition;
49  import org.apache.pluto.om.servlet.ServletDefinitionCtrl;
50  import org.apache.pluto.om.servlet.ServletDefinitionListCtrl;
51  import org.apache.pluto.portalImpl.om.common.impl.DescriptionImpl;
52  import org.apache.pluto.portalImpl.om.common.impl.DescriptionSetImpl;
53  import org.apache.pluto.portalImpl.om.common.impl.DisplayNameImpl;
54  import org.apache.pluto.portalImpl.om.common.impl.DisplayNameSetImpl;
55  import org.apache.pluto.portalImpl.om.portlet.impl.PortletApplicationDefinitionImpl;
56  import org.apache.pluto.portalImpl.om.servlet.impl.ServletDefinitionImpl;
57  import org.apache.pluto.portalImpl.om.servlet.impl.ServletMappingImpl;
58  import org.apache.pluto.portalImpl.om.servlet.impl.TagDefinitionImpl;
59  import org.apache.pluto.portalImpl.om.servlet.impl.WebApplicationDefinitionImpl;
60  import org.apache.pluto.portalImpl.xml.Constants;
61  import org.apache.pluto.portalImpl.xml.XmlParser;
62  import org.apache.xml.serialize.OutputFormat;
63  import org.apache.xml.serialize.XMLSerializer;
64  import org.exolab.castor.mapping.Mapping;
65  import org.exolab.castor.xml.Marshaller;
66  import org.exolab.castor.xml.Unmarshaller;
67  
68  public class Deploy {
69  
70      private static boolean debug = false;
71      private static String dirDelim = System.getProperty("file.separator");
72      private static String webInfDir = dirDelim + "WEB-INF" + dirDelim;
73      private static String webAppsDir;
74      private static String portalImplWebDir;
75      private static String plutoHome;
76  
77      public static void deployArchive(String webAppsDir, String warFile)
78          throws IOException {
79          String warFileName = warFile;
80          if (warFileName.indexOf("/") != -1)
81              warFileName =
82                  warFileName.substring(warFileName.lastIndexOf("/") + 1);
83          if (warFileName.indexOf(dirDelim) != -1)
84              warFileName =
85                  warFileName.substring(warFileName.lastIndexOf(dirDelim) + 1);
86          if (warFileName.endsWith(".war"))
87              warFileName =
88                  warFileName.substring(0, warFileName.lastIndexOf("."));
89  
90          System.out.println("deploying '" + warFileName + "' ...");
91  
92          String destination = webAppsDir + warFileName;
93  
94          JarFile jarFile = new JarFile(warFile);
95          Enumeration files = jarFile.entries();
96          while (files.hasMoreElements()) {
97              JarEntry entry = (JarEntry) files.nextElement();
98  
99  
100             /* Check for use of '/WEB-INF/tld/portlet.tld' instead of 'http://java.sun.com/portlet'" target="alexandria_uri">http://java.sun.com/portlet' in taglib declaration*/
101             String fileName = entry.getName();
102             if( !entry.isDirectory() && entry.getName().endsWith(".jsp")) {
103         		InputStream is = jarFile.getInputStream(entry);
104         		Reader r = new BufferedReader(new InputStreamReader(is));
105         		StreamTokenizer st = new StreamTokenizer(r);
106         		st.quoteChar('\'');
107         		st.quoteChar('"');
108         		while(st.nextToken()!=StreamTokenizer.TT_EOF) {
109         			if(st.ttype=='\'' || st.ttype=='"'){
110         				String sval = st.sval;
111         				String sqc = Character.toString((char)st.ttype);
112         				if(sval.equals("/WEB-INF/tld/portlet.tld")){
113         					System.out.println("Warning: " + sqc+st.sval+sqc + " has been found in file " + fileName + ". Use instead " +sqc+"http://java.sun.com/portlet"+sqc+" with your portlet taglib declaration!\n");
114         					break;
115         				}
116         			}
117         		}
118          	}
119 
120             File file = new File(destination, fileName);
121             File dirF = new File(file.getParent());
122             dirF.mkdirs();
123             if (entry.isDirectory()) {
124                 file.mkdirs();
125             } else {
126                 byte[] buffer = new byte[1024];
127                 int length = 0;
128                 InputStream fis = jarFile.getInputStream(entry);
129                 FileOutputStream fos = new FileOutputStream(file);
130                 while ((length = fis.read(buffer)) >= 0) {
131                     fos.write(buffer, 0, length);
132                 }
133                 fos.close();
134             }
135 
136         }
137 
138         System.out.println("finished!");
139     }
140 
141     public static void prepareWebArchive(String webAppsDir, String warFile)
142         throws Exception, IOException {
143         String webModule = warFile;
144         if (webModule.indexOf("/") != -1)
145             webModule = webModule.substring(webModule.lastIndexOf("/") + 1);
146         if (webModule.indexOf(dirDelim) != -1)
147             webModule =
148                 webModule.substring(webModule.lastIndexOf(dirDelim) + 1);
149         if (webModule.endsWith(".war"))
150             webModule = webModule.substring(0, webModule.lastIndexOf("."));
151 
152         System.out.println("prepare web archive '" + webModule + "' ...");
153 
154         Mapping mappingPortletXml = null;
155         Mapping mappingWebXml = null;
156 
157         // get portlet xml mapping file
158         String _portlet_mapping =
159             webAppsDir + portalImplWebDir + "WEB-INF" + dirDelim + "data" + dirDelim + "xml" +dirDelim + "portletdefinitionmapping.xml";
160         mappingPortletXml = new Mapping();
161         try {
162             mappingPortletXml.loadMapping(_portlet_mapping);
163         } catch (Exception e) {
164             System.out.println("CASTOR-Exception: " + e);
165             throw new IOException(
166                 "Failed to load mapping file " + _portlet_mapping);
167         }
168 
169         File portletXml =
170             new File(webAppsDir + webModule + webInfDir + "portlet.xml");
171 
172         // get web xml mapping file
173         String _web_mapping =
174             webAppsDir
175                 + portalImplWebDir
176                 + "WEB-INF" + dirDelim + "data" + dirDelim + "xml" + dirDelim + "servletdefinitionmapping.xml";
177         mappingWebXml = new Mapping();
178         try {
179             mappingWebXml.loadMapping(_web_mapping);
180         } catch (Exception e) {
181             throw new IOException(
182                 "Failed to load mapping file " + _web_mapping);
183         }
184 
185         File webXml = new File(webAppsDir + webModule + webInfDir + "web.xml");
186 
187         try {
188             org.w3c.dom.Document portletDocument =
189                 XmlParser.parsePortletXml(new FileInputStream(portletXml));
190 
191             Unmarshaller unmarshaller = new Unmarshaller(mappingPortletXml);
192 
193             // modified by YCLI: START :: to ignore extra elements and attributes
194             unmarshaller.setIgnoreExtraElements(true);
195             unmarshaller.setIgnoreExtraAttributes(true);
196             // modified by YCLI: END 
197 
198             PortletApplicationDefinitionImpl portletApp =
199                 (PortletApplicationDefinitionImpl) unmarshaller.unmarshal(
200                     portletDocument);
201 
202             // refill structure with necessary information
203             Vector structure = new Vector();
204             structure.add(webModule);
205             structure.add(null);
206             structure.add(null);
207             portletApp.preBuild(structure);
208 
209             if (debug) {
210                 System.out.println(portletApp);
211             }
212 
213             // now generate web part
214 
215             WebApplicationDefinitionImpl webApp = null;
216 
217             if (webXml.exists()) {
218                 org.w3c.dom.Document webDocument =
219                     XmlParser.parseWebXml(new FileInputStream(webXml));
220 
221                 Unmarshaller unmarshallerWeb = new Unmarshaller(mappingWebXml);
222 
223                 // modified by YCLI: START :: to ignore extra elements and attributes
224                 unmarshallerWeb.setIgnoreExtraElements(true);
225                 unmarshallerWeb.setIgnoreExtraAttributes(true);
226                 // modified by YCLI: END 
227 
228                 webApp =
229                     (WebApplicationDefinitionImpl) unmarshallerWeb.unmarshal(
230                         webDocument);
231             } else {
232                 webApp = new WebApplicationDefinitionImpl();
233                 DisplayNameImpl dispName = new DisplayNameImpl();
234                 dispName.setDisplayName(webModule);
235                 dispName.setLocale(Locale.ENGLISH);
236                 DisplayNameSetImpl dispSet = new DisplayNameSetImpl();
237                 dispSet.add(dispName);
238                 webApp.setDisplayNames(dispSet);
239                 DescriptionImpl desc = new DescriptionImpl();
240                 desc.setDescription("Automated generated Application Wrapper");
241                 desc.setLocale(Locale.ENGLISH);
242                 DescriptionSetImpl descSet = new DescriptionSetImpl();
243                 descSet.add(desc);
244                 webApp.setDescriptions(descSet);
245             }
246 
247             org.apache.pluto.om.ControllerFactory controllerFactory =
248                 new org.apache.pluto.portalImpl.om.ControllerFactoryImpl();
249 
250             ServletDefinitionListCtrl servletDefinitionSetCtrl =
251                 (ServletDefinitionListCtrl) controllerFactory.get(
252                     webApp.getServletDefinitionList());
253             Collection servletMappings = webApp.getServletMappings();
254 
255             Iterator portlets =
256                 portletApp.getPortletDefinitionList().iterator();
257             while (portlets.hasNext()) {
258 
259                 PortletDefinition portlet = (PortletDefinition) portlets.next();
260 
261                 // check if already exists
262                 ServletDefinition servlet =
263                     webApp.getServletDefinitionList().get(portlet.getName());
264                 if (servlet != null) {
265                     if (!servlet
266                         .getServletClass()
267                         .equals("org.apache.pluto.core.PortletServlet")) {
268                         System.out.println(
269                             "Note: Replaced already existing the servlet with the name '"
270                                 + portlet.getName()
271                                 + "' with the wrapper servlet.");
272                     }
273                     ServletDefinitionCtrl _servletCtrl =
274                         (ServletDefinitionCtrl) controllerFactory.get(servlet);
275                     _servletCtrl.setServletClass(
276                         "org.apache.pluto.core.PortletServlet");
277                 } else {
278                     servlet =
279                         servletDefinitionSetCtrl.add(
280                             portlet.getName(),
281                             "org.apache.pluto.core.PortletServlet");
282                 }
283 
284                 ServletDefinitionCtrl servletCtrl =
285                     (ServletDefinitionCtrl) controllerFactory.get(servlet);
286 
287                 DisplayNameImpl dispName = new DisplayNameImpl();
288                 dispName.setDisplayName(portlet.getName() + " Wrapper");
289                 dispName.setLocale(Locale.ENGLISH);
290                 DisplayNameSetImpl dispSet = new DisplayNameSetImpl();
291                 dispSet.add(dispName);
292                 servletCtrl.setDisplayNames(dispSet);
293                 DescriptionImpl desc = new DescriptionImpl();
294                 desc.setDescription("Automated generated Portlet Wrapper");
295                 desc.setLocale(Locale.ENGLISH);
296                 DescriptionSetImpl descSet = new DescriptionSetImpl();
297                 descSet.add(desc);
298                 servletCtrl.setDescriptions(descSet);
299                 ParameterSet parameters = servlet.getInitParameterSet();
300 
301                 ParameterSetCtrl parameterSetCtrl =
302                     (ParameterSetCtrl) controllerFactory.get(parameters);
303 
304                 Parameter parameter1 = parameters.get("portlet-class");
305                 if (parameter1 == null) {
306                     parameterSetCtrl.add(
307                         "portlet-class",
308                         portlet.getClassName());
309                 } else {
310                     ParameterCtrl parameterCtrl =
311                         (ParameterCtrl) controllerFactory.get(parameter1);
312                     parameterCtrl.setValue(portlet.getClassName());
313 
314                 }
315                 Parameter parameter2 = parameters.get("portlet-guid");
316                 if (parameter2 == null) {
317                     parameterSetCtrl.add(
318                         "portlet-guid",
319                         portlet.getId().toString());
320                 } else {
321                     ParameterCtrl parameterCtrl =
322                         (ParameterCtrl) controllerFactory.get(parameter2);
323                     parameterCtrl.setValue(portlet.getId().toString());
324 
325                 }
326 
327                 boolean found = false;
328                 Iterator mappings = servletMappings.iterator();
329                 while (mappings.hasNext()) {
330                     ServletMappingImpl servletMapping =
331                         (ServletMappingImpl) mappings.next();
332                     if (servletMapping
333                         .getServletName()
334                         .equals(portlet.getName())) {
335                         found = true;
336                         servletMapping.setUrlPattern(
337                             "/" + portlet.getName().replace(' ', '_') + "/*");
338                     }
339                 }
340                 if (!found) {
341                     ServletMappingImpl servletMapping =
342                         new ServletMappingImpl();
343                     servletMapping.setServletName(portlet.getName());
344                     servletMapping.setUrlPattern(
345                         "/" + portlet.getName().replace(' ', '_') + "/*");
346                     servletMappings.add(servletMapping);
347                 }
348 
349                 SecurityRoleRefSet servletSecurityRoleRefs =
350                     ((ServletDefinitionImpl)servlet).getInitSecurityRoleRefSet();
351 
352                 SecurityRoleRefSetCtrl servletSecurityRoleRefSetCtrl =
353                     (SecurityRoleRefSetCtrl) controllerFactory.get(
354                         servletSecurityRoleRefs);
355 
356                 SecurityRoleSet webAppSecurityRoles = webApp.getSecurityRoles();
357                     
358                 SecurityRoleRefSet portletSecurityRoleRefs =
359                     portlet.getInitSecurityRoleRefSet();
360 
361                 // TODO - Do we need this call? The variable is never read
362                 SecurityRoleRefSetCtrl portletSecurityRoleRefSetCtrl =
363                     (SecurityRoleRefSetCtrl) controllerFactory.get(
364                         portletSecurityRoleRefs);
365 
366                 Iterator p = portletSecurityRoleRefs.iterator();
367 
368                 while (p.hasNext()) {
369                     SecurityRoleRef portletSecurityRoleRef =
370                         (SecurityRoleRef) p.next();
371                     
372                     if (	portletSecurityRoleRef.getRoleLink()== null
373                         &&		
374                             webAppSecurityRoles.get(portletSecurityRoleRef.getRoleName())==null
375                     ){
376                         System.out.println(
377                             "Note: The web application has no security role defined which matches the role name \""
378                                 + portletSecurityRoleRef.getRoleName()
379                                 + "\" of the security-role-ref element defined for the wrapper-servlet with the name '"
380                                 + portlet.getName()
381                                 + "'.");
382                         break;						
383                     }
384                     SecurityRoleRef servletSecurityRoleRef =
385                         servletSecurityRoleRefs.get(
386                             portletSecurityRoleRef.getRoleName());
387                     if (null != servletSecurityRoleRef) {
388                         System.out.println(
389                             "Note: Replaced already existing element of type <security-role-ref> with value \""
390                                 + portletSecurityRoleRef.getRoleName()
391                                 + "\" for subelement of type <role-name> for the wrapper-servlet with the name '"
392                                 + portlet.getName()
393                                 + "'.");
394                         servletSecurityRoleRefSetCtrl.remove(
395                             servletSecurityRoleRef);
396                     }
397                     servletSecurityRoleRefSetCtrl.add(portletSecurityRoleRef);
398                 }
399 
400             }
401 
402             TagDefinitionImpl portletTagLib =
403                 new TagDefinitionImpl();
404             Collection taglibs = webApp.getCastorTagDefinitions();
405             taglibs.add(portletTagLib); 
406             
407 
408             if (debug) {
409                 System.out.println(webApp);
410             }
411 
412             OutputFormat of = new OutputFormat();
413             of.setIndenting(true);
414             of.setIndent(4); // 2-space indention
415             of.setLineWidth(16384);
416             // As large as needed to prevent linebreaks in text nodes
417             of.setDoctype(
418                 Constants.WEB_PORTLET_PUBLIC_ID,
419                 Constants.WEB_PORTLET_DTD);
420 
421             FileWriter writer =
422                 new FileWriter(webAppsDir + webModule + 
423                                                System.getProperty("file.separator") + "WEB-INF"+
424                                                System.getProperty("file.separator") + "web.xml");
425             XMLSerializer serializer = new XMLSerializer(writer, of);
426             try {
427             Marshaller marshaller =
428                 new Marshaller(serializer.asDocumentHandler());
429             marshaller.setMapping(mappingWebXml);
430             marshaller.marshal(webApp);
431             } catch (Exception e) {
432                 writer.close();
433                 e.printStackTrace(System.out);
434                 throw new Exception();
435             }
436             String strTo = dirDelim + "WEB-INF" + dirDelim + "tld" + dirDelim + "portlet.tld";
437             String strFrom = plutoHome + "portal" + dirDelim + "src" + 
438                 dirDelim + "webapp" + strTo;
439              
440             copy(strFrom, webAppsDir + webModule + strTo);
441         } catch (Exception e) {
442        
443             e.printStackTrace(System.out);
444             throw new Exception();
445         }
446 
447         System.out.println("finished!");
448     }
449 
450     public static void copy(String from, String to) throws IOException {
451         File f = new File(to);
452         f.getParentFile().mkdirs();
453         
454         byte[] buffer = new byte[1024];
455         int length = 0;
456         InputStream fis = new FileInputStream(from);
457         FileOutputStream fos = new FileOutputStream(f);
458         
459         while ((length = fis.read(buffer)) >= 0) {
460             fos.write(buffer, 0, length);
461         }
462         fos.close();
463     }
464 
465     public static void main(String args[]) {
466         String warFile;
467 
468 
469         if (args.length < 4) {
470             System.out.println(
471                 "No argument specified. This command must be issued as:");
472             System.out.println(
473                 "deploy <TOMCAT-webapps-directory> <TOMCAT-pluto-webmodule-name> <web-archive> <pluto-home-dir> [-debug] [-addToEntityReg <app-id> [<portlet-id>:<portlet-name>]+]");
474             return;
475         }
476 
477         if (args.length > 4) {
478             if ((args[4].equals("-debug")) || (args[4].equals("/debug"))) {
479                 debug = true;
480             }
481         }
482 
483         if(debug) {
484             for(int i=0; i<args.length;i++) {
485                 System.out.println( "args["+ i +"]:" + args[i]);				
486             }
487         }
488         
489         webAppsDir = args[0];
490         if (!webAppsDir.endsWith(dirDelim))
491             webAppsDir += dirDelim;
492 
493         portalImplWebDir = args[1];
494         if (!portalImplWebDir.endsWith(dirDelim))
495             portalImplWebDir += dirDelim;
496 
497         warFile = args[2];
498 
499         plutoHome = args[3];
500         if (!plutoHome.endsWith(dirDelim))
501             plutoHome += dirDelim;
502 
503         if (args.length > 4) {
504             if ((args[4].equals("-debug")) || (args[4].equals("/debug"))) {
505                 debug = true;
506             }
507             if (
508                   (args[4].equals("-addToEntityReg"))
509                || (  (args.length>5)
510                   && (args[5].equals("-addToEntityReg"))
511                   )
512             ) {
513                 // parameters: app-id   portlet application id; must be unique in portletentityregistry.xml
514                 //             portlet-id   portlet id; must be unique inside the portlet application
515                 //             portlet-name the name of the portlet in portlet.xml   
516                 addToEntityReg(args);
517             }
518         }
519 
520         try {
521             deployArchive(webAppsDir, warFile);
522 
523             prepareWebArchive(webAppsDir, warFile);
524         } catch (Exception e) {
525             e.printStackTrace(System.out);
526         }
527 
528     }
529 
530     static private void addToEntityReg(String[] args) {
531         File portletAppFile = new File(args[2]);
532         String portletAppFileName = portletAppFile.getName();
533         String portletApp =
534             portletAppFileName.substring(0,	portletAppFileName.lastIndexOf(".war"));
535         int o = (args[4].equals("-addToEntityReg") ? 5 : 6);
536         String appId = args[o++];
537         try {
538             String entityMapping = webAppsDir + portalImplWebDir
539   					               + "WEB-INF/data/portletentityregistry.xml";
540             File file = new File(entityMapping);
541             RandomAccessFile ras = new RandomAccessFile(file, "rw");
542             long length = ras.length();
543             byte[] contentByte = new byte[(int) length];
544             ras.read(contentByte);
545             String contentString = new String(contentByte);
546             long pos = contentString.lastIndexOf("</portlet-entity-registry>");
547             ras.seek(pos);
548             ras.writeBytes("    <application id=\"" + appId + "\">\r\n");
549             ras.writeBytes("        <definition-id>" + portletApp + "</definition-id>\r\n");
550 
551             StringTokenizer tokenizer;
552             for (int i = o; i < args.length; ++i) {
553                 tokenizer = new StringTokenizer(args[i], ":");
554                 String portletId = tokenizer.nextToken();
555                 String portletName = tokenizer.nextToken();
556                 ras.writeBytes("        <portlet id=\"" + portletId + "\">\r\n");
557                 ras.writeBytes("            <definition-id>" + portletApp
558                                + "." + portletName + "</definition-id>\r\n");
559                 ras.writeBytes("        </portlet>\r\n");
560             }
561             ras.writeBytes("    </application>\r\n");
562             ras.writeBytes("</portlet-entity-registry>\r\n");
563             ras.close();
564 
565         } catch (Exception e) {
566             e.printStackTrace(System.out);
567         }
568     }
569 
570 }