1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.pluto.portlet.admin.services;
17
18 import java.io.File;
19 import java.io.FileInputStream;
20 import java.io.FileNotFoundException;
21 import java.io.FileOutputStream;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.RandomAccessFile;
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.HashMap;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Properties;
32 import java.util.Set;
33 import java.util.zip.ZipEntry;
34 import java.util.zip.ZipFile;
35
36 import javax.portlet.ActionRequest;
37 import javax.portlet.ActionResponse;
38
39 import org.apache.commons.fileupload.FileItem;
40 import org.apache.commons.fileupload.FileUploadException;
41 import org.apache.commons.fileupload.PortletDiskFileUpload;
42 import org.apache.pluto.portlet.admin.BaseAdminObject;
43 import org.apache.pluto.portlet.admin.PlutoAdminConstants;
44 import org.apache.pluto.portlet.admin.PlutoAdminException;
45 import org.apache.pluto.portlet.admin.bean.PageTO;
46 import org.apache.pluto.portlet.admin.bean.PortletMessage;
47 import org.apache.pluto.portlet.admin.bean.PortletMessageType;
48 import org.apache.pluto.portlet.admin.bean.PortletTO;
49 import org.apache.pluto.portlet.admin.model.PageRegistryXao;
50 import org.apache.pluto.portlet.admin.model.PortletEntityRegistryXao;
51 import org.apache.pluto.portlet.admin.util.PlutoAdminContext;
52
53 /***
54 * This is the service that does is called by DeployWarPortlet to
55 * do the work of deploying a portlet war.
56 *
57 * @author Ken Atherton
58 * @author Craig Doremus
59 *
60 */
61 public class DeployWarService extends BaseAdminObject {
62
63 public static final String ERROR_NO_FILE = "ERROR_NO_FILE";
64 public static final String CLASS_NAME = "DeployWarService";
65
66 /***
67 * Default constructor
68 */
69 public DeployWarService() {
70 super(CLASS_NAME);
71 }
72
73 /***
74 * Constructor taking a String used to identify a logging record.
75 * @param logId
76 */
77 public DeployWarService(String logId) {
78 super(CLASS_NAME, logId);
79 }
80
81 /***
82 * Does the work of this service to deploy a portlet war file.
83 *
84 * @param request DeployWarService request object.
85 * @param response DeployWarService response object.
86 * @return
87 */
88 public String processFileUpload(ActionRequest request, ActionResponse response) {
89 final String METHOD_NAME = "processFileUpload(request,response)";
90 String fileName = null;
91 String serverFileName = null;
92 request.getPortletSession().setAttribute(PlutoAdminConstants.MESSAGE_ATTR, new PortletMessage("Deployment unsuccessful", PortletMessageType.ERROR));
93
94 if (PortletDiskFileUpload.isMultipartContent(request))
95 {
96
97 PortletDiskFileUpload dfu = new PortletDiskFileUpload();
98
99
100 dfu.setSizeMax(10 * 1000 * 1000);
101
102
103 dfu.setSizeThreshold(100 * 1000);
104
105 try
106 {
107
108 List fileItems = dfu.parseRequest(request);
109 Iterator iter = fileItems.iterator();
110 while (iter.hasNext())
111 {
112 FileItem item = (FileItem) iter.next();
113 if (item.isFormField())
114 {
115
116 String fieldName = item.getFieldName();
117 String value = item.getString();
118 response.setRenderParameter(fieldName, value);
119 }
120 else
121 {
122
123 fileName = item.getName();
124 String contentType = item.getContentType();
125 long size = item.getSize();
126 response.setRenderParameter("size", Long.toString(size));
127 response.setRenderParameter("contentType", contentType);
128 String tempDir = System.getProperty("java.io.tmpdir");
129 serverFileName = getRootFilename(File.separatorChar, fileName);
130 File serverFile = new File(tempDir, serverFileName);
131 item.write(serverFile);
132 response.setRenderParameter("serverFileName", serverFileName);
133
134
135 int index = serverFileName.indexOf(".war");
136 String context = "";
137 if ( index != -1) {
138 context = serverFileName.substring(0, index);
139 } else {
140 context = serverFileName;
141 }
142
143 PortletEntityRegistryXao xao = new PortletEntityRegistryXao();
144 boolean appExists = xao.applicationExists(context);
145 ArrayList argList = createDeploymentArgs(serverFileName, tempDir, request, appExists);
146 Map pmap = (HashMap) request.getPortletSession().getAttribute(PlutoAdminConstants.PORTLET_MAP_ATTR);
147 logDebug(METHOD_NAME, "Arguments for Deploy.main():");
148 String[] args = arrayListToStringArray(argList);
149 for (int i =0; i < args.length; i++) {
150 logDebug(METHOD_NAME, "args["+i+"]="+args[i]);
151 }
152 org.apache.pluto.portalImpl.Deploy.main(args);
153 if (appExists) {
154 request.getPortletSession().setAttribute(PlutoAdminConstants.MESSAGE_ATTR, new PortletMessage("Deployment of the new portlet app has been successful, but the portlet app record '" + context + "' already exists in portletentityregistry.xml. " +
155 "This may have occurred if the portlet was previously partially deployed. If that is the case, continue with this screen and the next to register the portlet in pageregistry.xml. " +
156 "If you are deploying a previously deployed portlet app, you should be able to see your changes if you select the portlet from the navigation bar. " +
157 "However, caching of the old app may require that you restart Pluto to see the new changes.", PortletMessageType.INFO));
158 } else {
159 request.getPortletSession().setAttribute(PlutoAdminConstants.MESSAGE_ATTR, new PortletMessage("Deployment and addition to portletentityregistry.xml successful.", PortletMessageType.SUCCESS));
160 }
161 }
162 }
163 }
164 catch (FileUploadException e){
165 String msg = "File Upload Exception: " + e.getMessage();
166 logError(METHOD_NAME, msg, e);
167 throw new PlutoAdminException(e);
168 } catch (Exception e) {
169 String msg = "Exception: " + e.getMessage();
170 logError(METHOD_NAME, msg, e);
171 throw new PlutoAdminException(e);
172 }
173 } else {
174
175 request.getPortletSession().setAttribute(PlutoAdminConstants.MESSAGE_ATTR, new PortletMessage("No file appears to have been selected.", PortletMessageType.ERROR));
176 }
177 logMethodEnd(METHOD_NAME, serverFileName);
178 return serverFileName;
179 }
180
181
182 private String getRootFilename(char delimiter, String pathName) {
183 int startFilenameIndex = pathName.lastIndexOf(delimiter) + 1;
184 String filename = pathName.substring(startFilenameIndex);
185 return filename;
186 }
187
188 private static String[] arrayListToStringArray(ArrayList argStringArrayList) {
189 return (String[]) argStringArrayList.toArray(new String[argStringArrayList.size()]);
190 }
191
192
193
194 private InputStream extractFile(String zipfilename, String filename) {
195 final String METHOD_NAME = "extractFile(zipfilename,filename)";
196 InputStream ins = null;
197 try {
198 ZipFile zf = new ZipFile(zipfilename);
199 if (null != zf) {
200 ZipEntry ze = zf.getEntry(filename);
201 if (null != ze) {
202 ins = zf.getInputStream(ze);
203 }
204 }
205 }
206 catch (Exception e) {
207 logError(CLASS_NAME, METHOD_NAME, e);
208 throw new PlutoAdminException(e);
209 }
210 return ins;
211 }
212
213
214
215 /***
216 * Creates arguments (parameters) for Deploy class that does
217 * the deployment.
218 *
219 * @param serverFileName The name of the war file to be deployed
220 * @param tempDir Full path to temp dir that holds the war file to be deployed
221 * @param request ActionRequest of the portlet.
222 * @param appExists True if this is a re-deployment, else false
223 * @return ArrayList of arguments
224 * @throws Exception
225 * @see org.apache.pluto.portalImpl.Deploy#main
226 */
227 private ArrayList createDeploymentArgs(String serverFileName, String tempDir, ActionRequest request, boolean appExists) throws Exception {
228 final String METHOD_NAME = "createDeploymentArgs(serverFileName,tempDir,request)";
229 Properties props = PlutoAdminContext.getProperties();
230 final String CONTAINER_HOME = PlutoAdminContext.getContainerHome();
231 final String PORTLET_DEPLOY_DIR = props.getProperty("portlet-deploy-dir");
232
233 ArrayList args = new ArrayList();
234 args.add(PlutoAdminContext.getDeploymentPath());
235 args.add(PlutoAdminContext.getPlutoWebContext());
236 args.add(tempDir + PlutoAdminConstants.FS + serverFileName);
237
238
239 args.add(CONTAINER_HOME + PlutoAdminConstants.FS + PORTLET_DEPLOY_DIR);
240 String appId = PortletRegistryService.getNextAppId();
241
242 if (!appExists) {
243 args.add("-addToEntityReg");
244 args.add(appId);
245 }
246
247
248
249 Map pmap = new HashMap();
250 InputStream ins = extractFile(tempDir + PlutoAdminConstants.FS + serverFileName, "WEB-INF/portlet.xml");
251 if (null != ins) {
252 ArrayList names = PortletNameFinder.getPortletNames(ins);
253 for (int i = 0; i < names.size(); i++) {
254
255 if (!appExists) {
256 args.add(i + ":" + names.get(i));
257 }
258 pmap.put(names.get(i), appId+"." +i);
259 }
260 ins.close();
261 } else {
262 String msg = "Input stream is null";
263 PlutoAdminException e = new PlutoAdminException(msg);
264 logError(METHOD_NAME, e);
265 throw e;
266 }
267 request.getPortletSession().setAttribute(PlutoAdminConstants.PORTLET_MAP_ATTR, pmap);
268 return args;
269 }
270
271
272 public static String mapToEntrySetString(Map inputMap) {
273 StringBuffer sb = new StringBuffer();
274 Set es = inputMap.entrySet();
275 Iterator it = es.iterator();
276 sb.append("Number of entries: " + es.size());
277 for (int i = 0; i < es.size(); i++) {
278 Map.Entry entry = (Map.Entry) it.next();
279 sb.append((String) entry.getKey().toString());
280 sb.append(entry.getValue().toString());
281 sb.append("\n");
282 }
283 return sb.toString();
284 }
285
286 /***
287 * Sets the page information into a PageTO object that is loaded into the
288 * session.
289 *
290 * @param req
291 */
292 public void setPage(ActionRequest req) {
293 final String METHOD_NAME = "setPage(request)";
294 logMethodStart(METHOD_NAME);
295 PageTO page = (PageTO)req.getPortletSession().getAttribute(PlutoAdminConstants.PAGE_ATTR);
296 if (page == null) {
297 page = new PageTO();
298 }
299 String title = req.getParameter("title");
300
301 page.setTitle(title);
302 String desc = req.getParameter("description");
303
304 page.setDescription(desc);
305 String rows = req.getParameter("numrows");
306
307 page.setRows(Integer.parseInt(rows));
308 String cols = req.getParameter("numcols");
309
310 page.setCols(Integer.parseInt(cols));
311 req.getPortletSession().setAttribute(PlutoAdminConstants.PAGE_ATTR, page);
312
313 logMethodEnd(METHOD_NAME);
314 }
315 public void savePageLayout(ActionRequest req) {
316 final String METHOD_NAME = "savePageLayout(request)";
317 logMethodStart(METHOD_NAME);
318
319 PageTO page = (PageTO)req.getPortletSession().getAttribute(PlutoAdminConstants.PAGE_ATTR);
320
321 List list = new ArrayList();
322 int rows = page.getRows();
323 int cols = page.getCols();
324 for (int i = 1; i <= rows ; i++) {
325 for (int j = 1; j <= cols ; j++) {
326 String portletParam = "portlet" + i + "." + j;
327 String name_val = req.getParameter(portletParam);
328
329 int underscore = name_val.lastIndexOf("_");
330 String name = name_val.substring(0, underscore);
331 String val = name_val.substring(underscore + 1);
332
333
334 PortletTO nPortlet = new PortletTO();
335 nPortlet.setName(name);
336 nPortlet.setValue(val);
337 nPortlet.setRow(i);
338 nPortlet.setCol(j);
339 list.add(nPortlet);
340 }
341 }
342 page.setPortlets(list);
343
344
345 addToPageReg(page);
346 logMethodEnd(METHOD_NAME);
347 }
348
349 /***
350 * Add a new page record to the pageregistry.xml file.
351 * @param page The new page to add
352 */
353 public void addToPageReg(PageTO page) {
354 final String METHOD_NAME = "addToPageReg(PageTO)";
355 logMethodStart(METHOD_NAME);
356 RandomAccessFile ras = null;
357
358
359 int cols = page.getCols();
360 String name = page.getName();
361 try {
362
363 String pageregpath = PlutoAdminContext.getInstance().getPageRegistryPath();
364
365
366 File file = new File(pageregpath);
367 ras = new RandomAccessFile(file, "rw");
368 long length = ras.length();
369 byte[] contentByte = new byte[(int) length];
370 ras.read(contentByte);
371 String contentString = new String(contentByte);
372
373 String prev = "fragment name=\"" + name;
374 if (contentString.lastIndexOf(prev) != -1){
375 String errMsg = "Portlet '" + name + "' already exists in pageregistry.xml";
376 PlutoAdminException e = new PlutoAdminException(errMsg);
377 logError(METHOD_NAME, errMsg, e);
378 throw e;
379 }
380
381 long pos = contentString.lastIndexOf("</portal>");
382 ras.seek(pos);
383
384
385 ras.writeBytes(" <fragment name=\"" + name + "\" type=\"page\" >" + PlutoAdminConstants.LS);
386 ras.writeBytes(" <navigation>" + PlutoAdminConstants.LS);
387 ras.writeBytes(" <title>" + page.getTitle());
388 ras.writeBytes("</title>" + PlutoAdminConstants.LS);
389 ras.writeBytes(" <description>" + page.getDescription());
390 ras.writeBytes("</description>" + PlutoAdminConstants.LS);
391 ras.writeBytes(" </navigation>" + PlutoAdminConstants.LS);
392
393
394 List portlets = page.getPortlets();
395
396
397 Collections.sort(portlets);
398 Iterator iter = portlets.iterator();
399 int count = 0;
400 int currRow = 0;
401 int lastRow = 0;
402 int currCol = 0;
403 while (iter.hasNext()) {
404 count++;
405 PortletTO portlet = (PortletTO)iter.next();
406 logDebug(METHOD_NAME, "Portlet: " + portlet);
407 currRow = portlet.getRow();
408 currCol = portlet.getCol();
409
410
411 if (currRow != lastRow) {
412 ras.writeBytes(" <fragment name=\"row" + currRow + "\" type=\"row\">" + PlutoAdminConstants.LS);
413 ras.writeBytes(" <fragment name=\"col" + count + "\" type=\"column\">" + PlutoAdminConstants.LS);
414 }
415
416 ras.writeBytes(" <fragment name=\"p" + count + "\" type=\"portlet\">" + PlutoAdminConstants.LS);
417 ras.writeBytes(" <property name=\"portlet\" value=\"" + portlet.getValue() + "\"/>" + PlutoAdminConstants.LS);
418 ras.writeBytes(" </fragment><!-- end of portlet frag -->" + PlutoAdminConstants.LS);
419
420
421 if (cols == currCol) {
422 ras.writeBytes(" </fragment><!-- end of col frag -->" + PlutoAdminConstants.LS);
423
424 ras.writeBytes(" </fragment><!-- end of row frag -->" + PlutoAdminConstants.LS);
425 }
426 lastRow = currRow;
427 }
428
429
430 ras.writeBytes(" </fragment><!-- end of 'page' frag -->" + PlutoAdminConstants.LS);
431
432 ras.writeBytes(PlutoAdminConstants.LS);
433 ras.writeBytes(PlutoAdminConstants.LS);
434
435 ras.writeBytes("</portal>" + PlutoAdminConstants.LS);
436
437 } catch (IOException e) {
438 logError(METHOD_NAME, e);
439 throw new PlutoAdminException(e);
440 } finally {
441 if (ras != null) {
442 try {
443 ras.close();
444 } catch (IOException e) {
445 logError(METHOD_NAME, e);
446 }
447 }
448 }
449 logMethodEnd(METHOD_NAME);
450 }
451
452 public boolean addToPortletContexts(String context) {
453 final String METHOD_NAME = "addToPortletContexts(context)";
454 logMethodStart(METHOD_NAME);
455 logParam(METHOD_NAME, "context", context);
456 String path = PlutoAdminContext.getInstance().getPortletContextsPath();
457 logDebug(METHOD_NAME, "portletcontexts.txt path: " + path);
458 File file = new File(path);
459 boolean found = false;
460 if (file.exists()) {
461 String fileContents = readFileToString(file);
462 logDebug(METHOD_NAME, "portletcontexts.txt contents: " + fileContents);
463
464
465
466 int ind = fileContents.indexOf(context);
467 found = ind == -1 ? false : true;
468
469
470
471
472
473 if (found && !fileContents.substring(ind - 1, ind).equals("/")) {
474 found = false;
475 }
476
477 if (found) {
478 int len = context.length();
479 String contextInFile = fileContents.substring(ind);
480 if (contextInFile.indexOf(PlutoAdminConstants.LS) != len) {
481 found = false;
482 }
483 }
484 if (!found) {
485 logDebug(METHOD_NAME, "Writing new context: " + context);
486 StringBuffer buf = new StringBuffer(fileContents);
487 buf.append(PlutoAdminConstants.LS);
488 buf.append("/");
489 buf.append(context);
490 writeStringToFile(file,buf.toString());
491 }
492 } else {
493 logWarn(METHOD_NAME, "File portletcontexts.txt cannot be found! You must be using Release Candidate 1.");
494 }
495 logMethodEnd(METHOD_NAME, Boolean.toString(found));
496 return found;
497 }
498
499
500 public boolean pageExists(String pageName) {
501 final String METHOD_NAME = "pageExists(pageName)";
502 boolean exists = true;
503 try {
504 PageRegistryXao xao = new PageRegistryXao();
505 exists = xao.pageExists(pageName);
506 } catch (Exception e) {
507 logError(METHOD_NAME, e);
508 throw new PlutoAdminException(e);
509 }
510 return exists;
511 }
512
513 public String readFileToString(File file){
514 final String METHOD_NAME = "readFileToString(path)";
515 String contents = null;
516 FileInputStream fis = null;
517 try {
518 fis = new FileInputStream(file);
519 int c;
520 char b;
521 StringBuffer sb = new StringBuffer();
522 while((c = fis.read()) != -1) {
523 b = (char)c;
524 sb.append(b);
525 }
526 contents = sb.toString().trim();
527 } catch (FileNotFoundException e) {
528 logError(METHOD_NAME, e);
529 throw new PlutoAdminException(e);
530 } catch (IOException e) {
531 logError(METHOD_NAME, e);
532 throw new PlutoAdminException(e);
533 } finally {
534 if (fis != null) {
535 try {
536 fis.close();
537 } catch (IOException e) {
538 logError(METHOD_NAME, e);
539 throw new PlutoAdminException(e);
540 }
541 }
542 }
543 return contents;
544 }
545
546 public void writeStringToFile(File file, String contents){
547 final String METHOD_NAME = "addFileToStringToFile(contents)";
548 FileOutputStream fos = null;
549 try {
550 fos = new FileOutputStream(file);
551 byte[] bytes = contents.getBytes();
552 fos.write(bytes);
553 } catch (FileNotFoundException e) {
554 logError(METHOD_NAME, e);
555 throw new PlutoAdminException(e);
556 } catch (IOException e) {
557 logError(METHOD_NAME, e);
558 throw new PlutoAdminException(e);
559 } finally {
560 if (fos != null) {
561 try {
562 fos.close();
563 } catch (IOException e) {
564 logError(METHOD_NAME, e);
565 throw new PlutoAdminException(e);
566 }
567 }
568 }
569 }
570
571 }