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