FELIX-1217: Second step: add multifile plugin to upload several bundles in one go
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@783783 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/webconsole/LICENSE.multifile b/webconsole/LICENSE.multifile
new file mode 100644
index 0000000..1e18bc3
--- /dev/null
+++ b/webconsole/LICENSE.multifile
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2008 Fyneworks.com
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/webconsole/NOTICE b/webconsole/NOTICE
index fbbb25f..7e3807b 100644
--- a/webconsole/NOTICE
+++ b/webconsole/NOTICE
@@ -29,6 +29,10 @@
Copyright (c) 2007 Christian Bach
Licensed under the MIT License
+This product includes software from http://www.fyneworks.com
+Copyright (c) 2008 Fyneworks.com
+Licensed under the MIT License
+
This product includes icons from the Silk Icon set
(http://www.famfamfam.com/lab/icons/silk/)
Copyright (c) 2006 Mark James
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/BundlesServlet.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/BundlesServlet.java
index c1b815e..946611c 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/BundlesServlet.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/BundlesServlet.java
@@ -294,7 +294,7 @@
if ( "upload".equals(reqInfo.pathInfo) )
{
- renderUploadForm(pw);
+ renderUploadForm(pw, appRoot);
}
else
{
@@ -307,14 +307,15 @@
}
}
- private void renderUploadForm( final PrintWriter pw ) throws IOException
+ private void renderUploadForm( final PrintWriter pw, final String appRoot ) throws IOException
{
+ Util.script(pw, appRoot, "jquery.multifile-1.4.6.min.js");
pw.println(" <div id='plugin_content'><div class='contentheader'>Upload / Install Bundles</div>");
pw.println( "<form method='post' enctype='multipart/form-data' action='../'>");
pw.println( "<input type='hidden' name='action' value='install'/>");
- pw.println( "<div class='contentline'><input class='fileinput' type='file' name='bundlefile'/></div>");
pw.println( "<div class='contentline'><div class='contentleft'>Start Bundle</div><div class='contentright'><input class='checkradio' type='checkbox' name='bundlestart' value='start'/></div></div>");
pw.println( "<div class='contentline'><div class='contentleft'>Start Level</div><div class='contentright'><input class='input' type='input' name='bundlestartlevel' value='" + getStartLevel().getInitialBundleStartLevel() + "' size='4'/></div></div>");
+ pw.println( "<div class='contentline'><input class='fileinput multi' accept='jar' type='file' name='bundlefile'/></div>");
pw.println( "<div class='contentline'><input type='submit' value='Install or Update'/></div>");
pw.println( "</form></div");
}
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/InstallAction.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/InstallAction.java
index 04a3c02..e880149 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/InstallAction.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/core/InstallAction.java
@@ -18,7 +18,7 @@
import java.io.*;
-import java.util.Map;
+import java.util.*;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
@@ -72,19 +72,19 @@
{
// get the uploaded data
- Map params = ( Map ) request.getAttribute( AbstractWebConsolePlugin.ATTR_FILEUPLOAD );
+ final Map params = ( Map ) request.getAttribute( AbstractWebConsolePlugin.ATTR_FILEUPLOAD );
if ( params == null )
{
return true;
}
- FileItem startItem = getFileItem( params, FIELD_START, true );
- FileItem startLevelItem = getFileItem( params, FIELD_STARTLEVEL, true );
- FileItem bundleItem = getFileItem( params, FIELD_BUNDLEFILE, false );
- FileItem refreshPackagesItem = getFileItem( params, FIELD_REFRESH_PACKAGES, true );
+ final FileItem startItem = getParameter( params, FIELD_START );
+ final FileItem startLevelItem = getParameter( params, FIELD_STARTLEVEL );
+ final FileItem[] bundleItems = getFileItems( params, FIELD_BUNDLEFILE );
+ final FileItem refreshPackagesItem = getParameter( params, FIELD_REFRESH_PACKAGES );
// don't care any more if not bundle item
- if ( bundleItem == null || bundleItem.getSize() <= 0 )
+ if ( bundleItems.length == 0 )
{
return true;
}
@@ -108,49 +108,54 @@
}
}
- // write the bundle data to a temporary file to ease processing
- File tmpFile = null;
- try
+ for(int i = 0; i < bundleItems.length; i++ )
{
- // copy the data to a file for better processing
- tmpFile = File.createTempFile( "install", ".tmp" );
- bundleItem.write( tmpFile );
- }
- catch ( Exception e )
- {
- getLog().log( LogService.LOG_ERROR, "Problem accessing uploaded bundle file", e );
+ final FileItem bundleItem = bundleItems[i];
+ getLog().log( LogService.LOG_ERROR, "Accessing uploaded bundle file: " + bundleItem.getName() );
+ // write the bundle data to a temporary file to ease processing
+ File tmpFile = null;
+ try
+ {
+ // copy the data to a file for better processing
+ tmpFile = File.createTempFile( "install", ".tmp" );
+ bundleItem.write( tmpFile );
+ }
+ catch ( Exception e )
+ {
+ getLog().log( LogService.LOG_ERROR, "Problem accessing uploaded bundle file: " + bundleItem.getName(), e );
- // remove the tmporary file
+ // remove the tmporary file
+ if ( tmpFile != null )
+ {
+ tmpFile.delete();
+ tmpFile = null;
+ }
+ }
+
+ // install or update the bundle now
if ( tmpFile != null )
{
- tmpFile.delete();
- tmpFile = null;
+ // start, refreshPackages just needs to exist, don't care for value
+ boolean start = startItem != null;
+ boolean refreshPackages = refreshPackagesItem != null;
+
+ bundleLocation = "inputstream:" + bundleItem.getName();
+ installBundle( bundleLocation, tmpFile, startLevel, start, refreshPackages );
}
}
- // install or update the bundle now
- if ( tmpFile != null )
- {
- // start, refreshPackages just needs to exist, don't care for value
- boolean start = startItem != null;
- boolean refreshPackages = refreshPackagesItem != null;
-
- bundleLocation = "inputstream:" + bundleItem.getName();
- installBundle( bundleLocation, tmpFile, startLevel, start, refreshPackages );
- }
-
return true;
}
- private FileItem getFileItem( Map params, String name, boolean isFormField )
+ private FileItem getParameter( Map params, String name )
{
FileItem[] items = ( FileItem[] ) params.get( name );
if ( items != null )
{
for ( int i = 0; i < items.length; i++ )
{
- if ( items[i].isFormField() == isFormField )
+ if ( items[i].isFormField() )
{
return items[i];
}
@@ -161,6 +166,23 @@
return null;
}
+ private FileItem[] getFileItems( Map params, String name )
+ {
+ final List files = new ArrayList();
+ FileItem[] items = ( FileItem[] ) params.get( name );
+ if ( items != null )
+ {
+ for ( int i = 0; i < items.length; i++ )
+ {
+ if ( !items[i].isFormField() && items[i].getSize() > 0 )
+ {
+ files.add(items[i]);
+ }
+ }
+ }
+
+ return (FileItem[])files.toArray(new FileItem[files.size()]);
+ }
private void installBundle( String location, File bundleFile, int startLevel, boolean start, boolean refreshPackages )
throws IOException
diff --git a/webconsole/src/main/resources/res/ui/jquery.multifile-1.4.6.min.js b/webconsole/src/main/resources/res/ui/jquery.multifile-1.4.6.min.js
new file mode 100644
index 0000000..548dfad
--- /dev/null
+++ b/webconsole/src/main/resources/res/ui/jquery.multifile-1.4.6.min.js
@@ -0,0 +1,11 @@
+/*
+ ### jQuery Multiple File Upload Plugin v1.46 - 2009-05-12 ###
+ * Home: http://www.fyneworks.com/jquery/multiple-file-upload/
+ * Code: http://code.google.com/p/jquery-multifile-plugin/
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ ###
+*/
+eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}(';3(U.1u)(6($){$.7.2=6(h){3(5.V==0)8 5;3(T S[0]==\'19\'){3(5.V>1){m i=S;8 5.M(6(){$.7.2.13($(5),i)})};$.7.2[S[0]].13(5,$.1N(S).27(1)||[]);8 5};m h=$.N({},$.7.2.F,h||{});$(\'2d\').1B(\'2-R\').Q(\'2-R\').1n($.7.2.Z);3($.7.2.F.15){$.7.2.1M($.7.2.F.15);$.7.2.F.15=10};5.1B(\'.2-1e\').Q(\'2-1e\').M(6(){U.2=(U.2||0)+1;m e=U.2;m g={e:5,E:$(5),L:$(5).L()};3(T h==\'21\')h={l:h};m o=$.N({},$.7.2.F,h||{},($.1m?g.E.1m():($.1S?g.E.17():10))||{},{});3(!(o.l>0)){o.l=g.E.D(\'28\');3(!(o.l>0)){o.l=(u(g.e.1D.B(/\\b(l|23)\\-([0-9]+)\\b/q)||[\'\']).B(/[0-9]+/q)||[\'\'])[0];3(!(o.l>0))o.l=-1;2b o.l=u(o.l).B(/[0-9]+/q)[0]}};o.l=18 2f(o.l);o.j=o.j||g.E.D(\'j\')||\'\';3(!o.j){o.j=(g.e.1D.B(/\\b(j\\-[\\w\\|]+)\\b/q))||\'\';o.j=18 u(o.j).t(/^(j|1d)\\-/i,\'\')};$.N(g,o||{});g.A=$.N({},$.7.2.F.A,g.A);$.N(g,{n:0,J:[],2c:[],1c:g.e.I||\'2\'+u(e),1i:6(z){8 g.1c+(z>0?\'1Z\'+u(z):\'\')},G:6(a,b){m c=g[a],k=$(b).D(\'k\');3(c){m d=c(b,k,g);3(d!=10)8 d}8 1a}});3(u(g.j).V>1){g.j=g.j.t(/\\W+/g,\'|\').t(/^\\W|\\W$/g,\'\');g.1k=18 2t(\'\\\\.(\'+(g.j?g.j:\'\')+\')$\',\'q\')};g.O=g.1c+\'1P\';g.E.1l(\'<P X="2-1l" I="\'+g.O+\'"></P>\');g.1q=$(\'#\'+g.O+\'\');g.e.H=g.e.H||\'p\'+e+\'[]\';3(!g.K){g.1q.1g(\'<P X="2-K" I="\'+g.O+\'1F"></P>\');g.K=$(\'#\'+g.O+\'1F\')};g.K=$(g.K);g.16=6(c,d){g.n++;c.2=g;3(d>0)c.I=c.H=\'\';3(d>0)c.I=g.1i(d);c.H=u(g.1j.t(/\\$H/q,$(g.L).D(\'H\')).t(/\\$I/q,$(g.L).D(\'I\')).t(/\\$g/q,e).t(/\\$i/q,d));3((g.l>0)&&((g.n-1)>(g.l)))c.14=1a;g.Y=g.J[d]=c;c=$(c);c.1b(\'\').D(\'k\',\'\')[0].k=\'\';c.Q(\'2-1e\');c.1V(6(){$(5).1X();3(!g.G(\'1Y\',5,g))8 y;m a=\'\',v=u(5.k||\'\');3(g.j&&v&&!v.B(g.1k))a=g.A.1o.t(\'$1d\',u(v.B(/\\.\\w{1,4}$/q)));1p(m f 2a g.J)3(g.J[f]&&g.J[f]!=5)3(g.J[f].k==v)a=g.A.1r.t(\'$p\',v.B(/[^\\/\\\\]+$/q));m b=$(g.L).L();b.Q(\'2\');3(a!=\'\'){g.1s(a);g.n--;g.16(b[0],d);c.1t().2e(b);c.C();8 y};$(5).1v({1w:\'1O\',1x:\'-1Q\'});c.1R(b);g.1y(5,d);g.16(b[0],d+1);3(!g.G(\'1T\',5,g))8 y});$(c).17(\'2\',g)};g.1y=6(c,d){3(!g.G(\'1U\',c,g))8 y;m r=$(\'<P X="2-1W"></P>\'),v=u(c.k||\'\'),a=$(\'<1z X="2-1A" 1A="\'+g.A.12.t(\'$p\',v)+\'">\'+g.A.p.t(\'$p\',v.B(/[^\\/\\\\]+$/q)[0])+\'</1z>\'),b=$(\'<a X="2-C" 2y="#\'+g.O+\'">\'+g.A.C+\'</a>\');g.K.1g(r.1g(b,\' \',a));b.1C(6(){3(!g.G(\'22\',c,g))8 y;g.n--;g.Y.14=y;g.J[d]=10;$(c).C();$(5).1t().C();$(g.Y).1v({1w:\'\',1x:\'\'});$(g.Y).11().1b(\'\').D(\'k\',\'\')[0].k=\'\';3(!g.G(\'24\',c,g))8 y;8 y});3(!g.G(\'25\',c,g))8 y};3(!g.2)g.16(g.e,0);g.n++;g.E.17(\'2\',g)})};$.N($.7.2,{11:6(){m a=$(5).17(\'2\');3(a)a.K.26(\'a.2-C\').1C();8 $(5)},Z:6(a){a=(T(a)==\'19\'?a:\'\')||\'1E\';m o=[];$(\'1h:p.2\').M(6(){3($(5).1b()==\'\')o[o.V]=5});8 $(o).M(6(){5.14=1a}).Q(a)},1f:6(a){a=(T(a)==\'19\'?a:\'\')||\'1E\';8 $(\'1h:p.\'+a).29(a).M(6(){5.14=y})},R:{},1M:6(b,c,d){m e,k;d=d||[];3(d.1G.1H().1I("1J")<0)d=[d];3(T(b)==\'6\'){$.7.2.Z();k=b.13(c||U,d);1K(6(){$.7.2.1f()},1L);8 k};3(b.1G.1H().1I("1J")<0)b=[b];1p(m i=0;i<b.V;i++){e=b[i]+\'\';3(e)(6(a){$.7.2.R[a]=$.7[a]||6(){};$.7[a]=6(){$.7.2.Z();k=$.7.2.R[a].13(5,S);1K(6(){$.7.2.1f()},1L);8 k}})(e)}}});$.7.2.F={j:\'\',l:-1,1j:\'$H\',A:{C:\'x\',1o:\'2g 2h 2i a $1d p.\\2j 2k...\',p:\'$p\',12:\'2l 12: $p\',1r:\'2m p 2n 2o 2p 12:\\n$p\'},15:[\'1n\',\'2q\',\'2r\',\'2s\'],1s:6(s){2u(s)}};$.7.11=6(){8 5.M(6(){2v{5.11()}2w(e){}})};$(6(){$("1h[2x=p].20").2()})})(1u);',62,159,'||MultiFile|if||this|function|fn|return|||||||||||accept|value|max|var|||file|gi|||replace|String||||false||STRING|match|remove|attr||options|trigger|name|id|slaves|list|clone|each|extend|wrapID|div|addClass|intercepted|arguments|typeof|window|length||class|current|disableEmpty|null|reset|selected|apply|disabled|autoIntercept|addSlave|data|new|string|true|val|instanceKey|ext|applied|reEnableEmpty|append|input|generateID|namePattern|rxAccept|wrap|metadata|submit|denied|for|wrapper|duplicate|error|parent|jQuery|css|position|top|addToList|span|title|not|click|className|mfD|_list|constructor|toString|indexOf|Array|setTimeout|1000|intercept|makeArray|absolute|_wrap|3000px|after|meta|afterFileSelect|onFileAppend|change|label|blur|onFileSelect|_F|multi|number|onFileRemove|limit|afterFileRemove|afterFileAppend|find|slice|maxlength|removeClass|in|else|files|form|prepend|Number|You|cannot|select|nTry|again|File|This|has|already|been|ajaxSubmit|ajaxForm|validate|RegExp|alert|try|catch|type|href'.split('|'),0,{}))
\ No newline at end of file