# HG changeset patch # User Eugene Ostroukhov # Date 1271199848 25200 # Node ID a619b3ef30957048c98380b47ed1e81498ccd264 # Parent 60453502674ed83433800e0b1f75fe34183a15e7 Bug 2482 - Store previewer user information in workspace diff -r 60453502674e -r a619b3ef3095 org.symbian.tools.wrttools.previewer/.classpath --- a/org.symbian.tools.wrttools.previewer/.classpath Fri Apr 09 17:07:39 2010 -0700 +++ b/org.symbian.tools.wrttools.previewer/.classpath Tue Apr 13 16:04:08 2010 -0700 @@ -1,5 +1,6 @@ + diff -r 60453502674e -r a619b3ef3095 org.symbian.tools.wrttools.previewer/META-INF/MANIFEST.MF --- a/org.symbian.tools.wrttools.previewer/META-INF/MANIFEST.MF Fri Apr 09 17:07:39 2010 -0700 +++ b/org.symbian.tools.wrttools.previewer/META-INF/MANIFEST.MF Tue Apr 13 16:04:08 2010 -0700 @@ -23,3 +23,5 @@ org.eclipse.equinox.jsp.jasper;version="1.0.0", org.osgi.service.http;version="1.2.1" Bundle-Vendor: Symbian Foundation +Bundle-ClassPath: lib/json_simple/json_simple-1.1.jar, + . diff -r 60453502674e -r a619b3ef3095 org.symbian.tools.wrttools.previewer/build.properties --- a/org.symbian.tools.wrttools.previewer/build.properties Fri Apr 09 17:07:39 2010 -0700 +++ b/org.symbian.tools.wrttools.previewer/build.properties Tue Apr 13 16:04:08 2010 -0700 @@ -7,7 +7,9 @@ preferences.ini,\ icons/,\ wrt.xml,\ - http-content/ # javac + http-content/,\ + lib/json_simple/json_simple-1.1.jar +# javac javacSource=1.5 javacTarget=1.5 javacVerbose=true diff -r 60453502674e -r a619b3ef3095 org.symbian.tools.wrttools.previewer/lib/json_simple/AUTHORS.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.symbian.tools.wrttools.previewer/lib/json_simple/AUTHORS.txt Tue Apr 13 16:04:08 2010 -0700 @@ -0,0 +1,1 @@ +Fang Yidong \ No newline at end of file diff -r 60453502674e -r a619b3ef3095 org.symbian.tools.wrttools.previewer/lib/json_simple/LICENSE.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.symbian.tools.wrttools.previewer/lib/json_simple/LICENSE.txt Tue Apr 13 16:04:08 2010 -0700 @@ -0,0 +1,162 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, +and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the +copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other +entities that control, are controlled by, or are under common control +with that entity. For the purposes of this definition, "control" means +(i) the power, direct or indirect, to cause the direction or management +of such entity, whether by contract or otherwise, or (ii) ownership of +fifty percent (50%) or more of the outstanding shares, or (iii) beneficial +ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, +including but not limited to software source code, documentation source, +and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation +or translation of a Source form, including but not limited to compiled object +code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, +made available under the License, as indicated by a copyright notice that is +included in or attached to the work (an example is provided in the Appendix +below). + +"Derivative Works" shall mean any work, whether in Source or Object form, +that is based on (or derived from) the Work and for which the editorial +revisions, annotations, elaborations, or other modifications represent, +as a whole, an original work of authorship. For the purposes of this License, +Derivative Works shall not include works that remain separable from, or merely +link (or bind by name) to the interfaces of, the Work and Derivative Works +thereof. + +"Contribution" shall mean any work of authorship, including the original +version of the Work and any modifications or additions to that Work or +Derivative Works thereof, that is intentionally submitted to Licensor for +inclusion in the Work by the copyright owner or by an individual or Legal +Entity authorized to submit on behalf of the copyright owner. For the purposes +of this definition, "submitted" means any form of electronic, verbal, or +written communication sent to the Licensor or its representatives, including +but not limited to communication on electronic mailing lists, source code +control systems, and issue tracking systems that are managed by, or on behalf +of, the Licensor for the purpose of discussing and improving the Work, but +excluding communication that is conspicuously marked or otherwise designated +in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this +License, each Contributor hereby grants to You a perpetual, worldwide, +non-exclusive, no-charge, royalty-free, irrevocable copyright license to +reproduce, prepare Derivative Works of, publicly display, publicly perform, +sublicense, and distribute the Work and such Derivative Works in Source or +Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this +License, each Contributor hereby grants to You a perpetual, worldwide, +non-exclusive, no-charge, royalty-free, irrevocable (except as stated in +this section) patent license to make, have made, use, offer to sell, sell, +import, and otherwise transfer the Work, where such license applies only +to those patent claims licensable by such Contributor that are necessarily +infringed by their Contribution(s) alone or by combination of their +Contribution(s) with the Work to which such Contribution(s) was submitted. +If You institute patent litigation against any entity (including a cross-claim +or counterclaim in a lawsuit) alleging that the Work or a Contribution +incorporated within the Work constitutes direct or contributory patent +infringement, then any patent licenses granted to You under this License +for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or +Derivative Works thereof in any medium, with or without modifications, +and in Source or Object form, provided that You meet the following conditions: + + 1. You must give any other recipients of the Work or Derivative Works a copy +of this License; and + + 2. You must cause any modified files to carry prominent notices stating that +You changed the files; and + + 3. You must retain, in the Source form of any Derivative Works that You +distribute, all copyright, patent, trademark, and attribution notices from +the Source form of the Work, excluding those notices that do not pertain to +any part of the Derivative Works; and + + 4. If the Work includes a "NOTICE" text file as part of its distribution, +then any Derivative Works that You distribute must include a readable copy +of the attribution notices contained within such NOTICE file, excluding those +notices that do not pertain to any part of the Derivative Works, in at least +one of the following places: within a NOTICE text file distributed as part of +the Derivative Works; within the Source form or documentation, if provided +along with the Derivative Works; or, within a display generated by the +Derivative Works, if and wherever such third-party notices normally appear. +The contents of the NOTICE file are for informational purposes only and do +not modify the License. You may add Your own attribution notices within +Derivative Works that You distribute, alongside or as an addendum to the +NOTICE text from the Work, provided that such additional attribution notices +cannot be construed as modifying the License. + +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, +or distribution of Your modifications, or for any such Derivative Works as a +whole, provided Your use, reproduction, and distribution of the Work otherwise +complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, +any Contribution intentionally submitted for inclusion in the Work by You +to the Licensor shall be under the terms and conditions of this License, +without any additional terms or conditions. Notwithstanding the above, +nothing herein shall supersede or modify the terms of any separate license +agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, +trademarks, service marks, or product names of the Licensor, except as +required for reasonable and customary use in describing the origin of the +Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to +in writing, Licensor provides the Work (and each Contributor provides its +Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied, including, without limitation, any warranties +or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A +PARTICULAR PURPOSE. You are solely responsible for determining the +appropriateness of using or redistributing the Work and assume any risks +associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether +in tort (including negligence), contract, or otherwise, unless required by +applicable law (such as deliberate and grossly negligent acts) or agreed to +in writing, shall any Contributor be liable to You for damages, including +any direct, indirect, special, incidental, or consequential damages of any +character arising as a result of this License or out of the use or inability +to use the Work (including but not limited to damages for loss of goodwill, +work stoppage, computer failure or malfunction, or any and all other +commercial damages or losses), even if such Contributor has been advised of +the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work +or Derivative Works thereof, You may choose to offer, and charge a fee for, +acceptance of support, warranty, indemnity, or other liability obligations +and/or rights consistent with this License. However, in accepting such +obligations, You may act only on Your own behalf and on Your sole +responsibility, not on behalf of any other Contributor, and only if You agree +to indemnify, defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason of your +accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff -r 60453502674e -r a619b3ef3095 org.symbian.tools.wrttools.previewer/lib/json_simple/README.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.symbian.tools.wrttools.previewer/lib/json_simple/README.txt Tue Apr 13 16:04:08 2010 -0700 @@ -0,0 +1,144 @@ +Simple Java toolkit for JSON (JSON.simple) +========================================== + +1.Why the Simple Java toolkit (also named as JSON.simple) for JSON? + + When I use JSON as the data exchange format between the AJAX client and JSP + for the first time, what worry me mostly is how to encode Java strings and + numbers correctly in the server side so the AJAX client will receive a well + formed JSON data. When I looked into the 'JSON in Java' directory in JSON + website,I found that wrappers to JSONObject and JSONArray can be simpler, + due to the simplicity of JSON itself. So I wrote the JSON.simple package. + +2.Is it simple,really? + + I think so. Take an example: + + import org.json.simple.JSONObject; + + JSONObject obj=new JSONObject(); + obj.put("name","foo"); + obj.put("num",new Integer(100)); + obj.put("balance",new Double(1000.21)); + obj.put("is_vip",new Boolean(true)); + obj.put("nickname",null); + System.out.print(obj); + + Result: + {"nickname":null,"num":100,"balance":1000.21,"is_vip":true,"name":"foo"} + + The JSONObject.toString() will escape controls and specials correctly. + +3.How to use JSON.simple in JSP? + + Take an example in JSP: + + <%@page contentType="text/html; charset=UTF-8"%> + <%@page import="org.json.simple.JSONObject"%> + <% + JSONObject obj=new JSONObject(); + obj.put("name","foo"); + obj.put("num",new Integer(100)); + obj.put("balance",new Double(1000.21)); + obj.put("is_vip",new Boolean(true)); + obj.put("nickname",null); + out.print(obj); + out.flush(); + %> + + So the AJAX client will get the responseText. + +4.Some details about JSONObject? + + JSONObject inherits java.util.HashMap,so it don't have to worry about the + mapping things between keys and values. Feel free to use the Map methods + like get(), put(), and remove() and others. JSONObject.toString() will + combine key value pairs to get the JSON data string. Values will be escaped + into JSON quote string format if it's an instance of java.lang.String. Other + type of instance like java.lang.Number,java.lang.Boolean,null,JSONObject and + JSONArray will NOT escape, just take their java.lang.String.valueOf() result. + null value will be the JSON 'null' in the result. + + It's still correct if you put an instance of JSONObject or JSONArray into an + instance of JSONObject or JSONArray. Take the example about: + + JSONObject obj2=new JSONObject(); + obj2.put("phone","123456"); + obj2.put("zip","7890"); + obj.put("contact",obj2); + System.out.print(obj); + + Result: + {"nickname":null,"num":100,"contact":{"phone":"123456","zip":"7890"},"balance":1000.21,"is_vip":true,"name":"foo"} + + The method JSONObject.escape() is used to escape Java string into JSON quote + string. Controls and specials will be escaped correctly into \b,\f,\r,\n,\t, + \",\\,\/,\uhhhh. + +5.Some detail about JSONArray? + + org.json.simple.JSONArray inherits java.util.ArrayList. Feel free to use the + List methods like get(),add(),remove(),iterator() and so on. The rules of + JSONArray.toString() is similar to JSONObject.toString(). Here's the example: + + import org.json.simple.JSONArray; + + JSONArray array=new JSONArray(); + array.add("hello"); + array.add(new Integer(123)); + array.add(new Boolean(false)); + array.add(null); + array.add(new Double(123.45)); + array.add(obj2);//see above + System.out.print(array); + + Result: + ["hello",123,false,null,123.45,{"phone":"123456","zip":"7890"}] + +6.What is JSONValue for? + + org.json.simple.JSONValue is use to parse JSON data into Java Object. + In JSON, the topmost entity is JSON value, not the JSON object. But + it's not necessary to wrap JSON string,boolean,number and null again, + for the Java has already had the according classes: java.lang.String, + java.lang.Boolean,java.lang.Number and null. The mapping is: + + JSON Java + ------------------------------------------------ + string <=> java.lang.String + number <=> java.lang.Number + true|false <=> java.lang.Boolean + null <=> null + array <=> org.json.simple.JSONArray + object <=> org.json.simple.JSONObject + ------------------------------------------------ + + JSONValue has only one kind of method, JSONValue.parse(), which receives + a java.io.Reader or java.lang.String. Return type of JSONValue.parse() + is according to the mapping above. If the input is incorrect in syntax or + there's exceptions during the parsing, I choose to return null, ignoring + the exception: I have no idea if it's a serious implementaion, but I think + it's convenient to the user. + + Here's the example: + + String s="[0,{\"1\":{\"2\":{\"3\":{\"4\":[5,{\"6\":7}]}}}}]"; + Object obj=JSONValue.parse(s); + JSONArray array=(JSONArray)obj; + System.out.println(array.get(1)); + JSONObject obj2=(JSONObject)array.get(1); + System.out.println(obj2.get("1")); + + Result: + {"1":{"2":{"3":{"4":[5,{"6":7}]}}}} + {"2":{"3":{"4":[5,{"6":7}]}}} + +7.About the author. + + I'm a Java EE developer on Linux. + I'm working on web systems and information retrieval systems. + I also develop 3D games and Flash games. + + You can contact me through: + Fang Yidong + Fang Yidong diff -r 60453502674e -r a619b3ef3095 org.symbian.tools.wrttools.previewer/lib/json_simple/json_simple-1.1.jar Binary file org.symbian.tools.wrttools.previewer/lib/json_simple/json_simple-1.1.jar has changed diff -r 60453502674e -r a619b3ef3095 org.symbian.tools.wrttools.previewer/preview/script/jquery-ui/js/jquery-1.2.6.min.js --- a/org.symbian.tools.wrttools.previewer/preview/script/jquery-ui/js/jquery-1.2.6.min.js Fri Apr 09 17:07:39 2010 -0700 +++ b/org.symbian.tools.wrttools.previewer/preview/script/jquery-ui/js/jquery-1.2.6.min.js Tue Apr 13 16:04:08 2010 -0700 @@ -1,3 +1,4 @@ +(function(){ /* * jQuery 1.2.6 - New Wave Javascript * @@ -8,25 +9,3541 @@ * $Date: 2008-05-24 14:22:17 -0400 (Sat, 24 May 2008) $ * $Rev: 5685 $ */ -(function(){var _jQuery=window.jQuery,_$=window.$;var jQuery=window.jQuery=window.$=function(selector,context){return new jQuery.fn.init(selector,context);};var quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/,isSimple=/^.[^:#\[\.]*$/,undefined;jQuery.fn=jQuery.prototype={init:function(selector,context){selector=selector||document;if(selector.nodeType){this[0]=selector;this.length=1;return this;}if(typeof selector=="string"){var match=quickExpr.exec(selector);if(match&&(match[1]||!context)){if(match[1])selector=jQuery.clean([match[1]],context);else{var elem=document.getElementById(match[3]);if(elem){if(elem.id!=match[3])return jQuery().find(selector);return jQuery(elem);}selector=[];}}else -return jQuery(context).find(selector);}else if(jQuery.isFunction(selector))return jQuery(document)[jQuery.fn.ready?"ready":"load"](selector);return this.setArray(jQuery.makeArray(selector));},jquery:"1.2.6",size:function(){return this.length;},length:0,get:function(num){return num==undefined?jQuery.makeArray(this):this[num];},pushStack:function(elems){var ret=jQuery(elems);ret.prevObject=this;return ret;},setArray:function(elems){this.length=0;Array.prototype.push.apply(this,elems);return this;},each:function(callback,args){return jQuery.each(this,callback,args);},index:function(elem){var ret=-1;return jQuery.inArray(elem&&elem.jquery?elem[0]:elem,this);},attr:function(name,value,type){var options=name;if(name.constructor==String)if(value===undefined)return this[0]&&jQuery[type||"attr"](this[0],name);else{options={};options[name]=value;}return this.each(function(i){for(name in options)jQuery.attr(type?this.style:this,name,jQuery.prop(this,options[name],type,i,name));});},css:function(key,value){if((key=='width'||key=='height')&&parseFloat(value)<0)value=undefined;return this.attr(key,value,"curCSS");},text:function(text){if(typeof text!="object"&&text!=null)return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(text));var ret="";jQuery.each(text||this,function(){jQuery.each(this.childNodes,function(){if(this.nodeType!=8)ret+=this.nodeType!=1?this.nodeValue:jQuery.fn.text([this]);});});return ret;},wrapAll:function(html){if(this[0])jQuery(html,this[0].ownerDocument).clone().insertBefore(this[0]).map(function(){var elem=this;while(elem.firstChild)elem=elem.firstChild;return elem;}).append(this);return this;},wrapInner:function(html){return this.each(function(){jQuery(this).contents().wrapAll(html);});},wrap:function(html){return this.each(function(){jQuery(this).wrapAll(html);});},append:function(){return this.domManip(arguments,true,false,function(elem){if(this.nodeType==1)this.appendChild(elem);});},prepend:function(){return this.domManip(arguments,true,true,function(elem){if(this.nodeType==1)this.insertBefore(elem,this.firstChild);});},before:function(){return this.domManip(arguments,false,false,function(elem){this.parentNode.insertBefore(elem,this);});},after:function(){return this.domManip(arguments,false,true,function(elem){this.parentNode.insertBefore(elem,this.nextSibling);});},end:function(){return this.prevObject||jQuery([]);},find:function(selector){var elems=jQuery.map(this,function(elem){return jQuery.find(selector,elem);});return this.pushStack(/[^+>] [^+>]/.test(selector)||selector.indexOf("..")>-1?jQuery.unique(elems):elems);},clone:function(events){var ret=this.map(function(){if(jQuery.browser.msie&&!jQuery.isXMLDoc(this)){var clone=this.cloneNode(true),container=document.createElement("div");container.appendChild(clone);return jQuery.clean([container.innerHTML])[0];}else -return this.cloneNode(true);});var clone=ret.find("*").andSelf().each(function(){if(this[expando]!=undefined)this[expando]=null;});if(events===true)this.find("*").andSelf().each(function(i){if(this.nodeType==3)return;var events=jQuery.data(this,"events");for(var type in events)for(var handler in events[type])jQuery.event.add(clone[i],type,events[type][handler],events[type][handler].data);});return ret;},filter:function(selector){return this.pushStack(jQuery.isFunction(selector)&&jQuery.grep(this,function(elem,i){return selector.call(elem,i);})||jQuery.multiFilter(selector,this));},not:function(selector){if(selector.constructor==String)if(isSimple.test(selector))return this.pushStack(jQuery.multiFilter(selector,this,true));else -selector=jQuery.multiFilter(selector,this);var isArrayLike=selector.length&&selector[selector.length-1]!==undefined&&!selector.nodeType;return this.filter(function(){return isArrayLike?jQuery.inArray(this,selector)<0:this!=selector;});},add:function(selector){return this.pushStack(jQuery.unique(jQuery.merge(this.get(),typeof selector=='string'?jQuery(selector):jQuery.makeArray(selector))));},is:function(selector){return!!selector&&jQuery.multiFilter(selector,this).length>0;},hasClass:function(selector){return this.is("."+selector);},val:function(value){if(value==undefined){if(this.length){var elem=this[0];if(jQuery.nodeName(elem,"select")){var index=elem.selectedIndex,values=[],options=elem.options,one=elem.type=="select-one";if(index<0)return null;for(var i=one?index:0,max=one?index+1:options.length;i=0||jQuery.inArray(this.name,value)>=0);else if(jQuery.nodeName(this,"select")){var values=jQuery.makeArray(value);jQuery("option",this).each(function(){this.selected=(jQuery.inArray(this.value,values)>=0||jQuery.inArray(this.text,values)>=0);});if(!values.length)this.selectedIndex=-1;}else -this.value=value;});},html:function(value){return value==undefined?(this[0]?this[0].innerHTML:null):this.empty().append(value);},replaceWith:function(value){return this.after(value).remove();},eq:function(i){return this.slice(i,i+1);},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments));},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem);}));},andSelf:function(){return this.add(this.prevObject);},data:function(key,value){var parts=key.split(".");parts[1]=parts[1]?"."+parts[1]:"";if(value===undefined){var data=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);if(data===undefined&&this.length)data=jQuery.data(this[0],key);return data===undefined&&parts[1]?this.data(parts[0]):data;}else -return this.trigger("setData"+parts[1]+"!",[parts[0],value]).each(function(){jQuery.data(this,key,value);});},removeData:function(key){return this.each(function(){jQuery.removeData(this,key);});},domManip:function(args,table,reverse,callback){var clone=this.length>1,elems;return this.each(function(){if(!elems){elems=jQuery.clean(args,this.ownerDocument);if(reverse)elems.reverse();}var obj=this;if(table&&jQuery.nodeName(this,"table")&&jQuery.nodeName(elems[0],"tr"))obj=this.getElementsByTagName("tbody")[0]||this.appendChild(this.ownerDocument.createElement("tbody"));var scripts=jQuery([]);jQuery.each(elems,function(){var elem=clone?jQuery(this).clone(true)[0]:this;if(jQuery.nodeName(elem,"script"))scripts=scripts.add(elem);else{if(elem.nodeType==1)scripts=scripts.add(jQuery("script",elem).remove());callback.call(obj,elem);}});scripts.each(evalScript);});}};jQuery.fn.init.prototype=jQuery.fn;function evalScript(i,elem){if(elem.src)jQuery.ajax({url:elem.src,async:false,dataType:"script"});else -jQuery.globalEval(elem.text||elem.textContent||elem.innerHTML||"");if(elem.parentNode)elem.parentNode.removeChild(elem);}function now(){return+new Date;}jQuery.extend=jQuery.fn.extend=function(){var target=arguments[0]||{},i=1,length=arguments.length,deep=false,options;if(target.constructor==Boolean){deep=target;target=arguments[1]||{};i=2;}if(typeof target!="object"&&typeof target!="function")target={};if(length==i){target=this;--i;}for(;i-1;}},swap:function(elem,options,callback){var old={};for(var name in options){old[name]=elem.style[name];elem.style[name]=options[name];}callback.call(elem);for(var name in options)elem.style[name]=old[name];},css:function(elem,name,force){if(name=="width"||name=="height"){var val,props={position:"absolute",visibility:"hidden",display:"block"},which=name=="width"?["Left","Right"]:["Top","Bottom"];function getWH(){val=name=="width"?elem.offsetWidth:elem.offsetHeight;var padding=0,border=0;jQuery.each(which,function(){padding+=parseFloat(jQuery.curCSS(elem,"padding"+this,true))||0;border+=parseFloat(jQuery.curCSS(elem,"border"+this+"Width",true))||0;});val-=Math.round(padding+border);}if(jQuery(elem).is(":visible"))getWH();else -jQuery.swap(elem,props,getWH);return Math.max(0,val);}return jQuery.curCSS(elem,name,force);},curCSS:function(elem,name,force){var ret,style=elem.style;function color(elem){if(!jQuery.browser.safari)return false;var ret=defaultView.getComputedStyle(elem,null);return!ret||ret.getPropertyValue("color")=="";}if(name=="opacity"&&jQuery.browser.msie){ret=jQuery.attr(style,"opacity");return ret==""?"1":ret;}if(jQuery.browser.opera&&name=="display"){var save=style.outline;style.outline="0 solid black";style.outline=save;}if(name.match(/float/i))name=styleFloat;if(!force&&style&&style[name])ret=style[name];else if(defaultView.getComputedStyle){if(name.match(/float/i))name="float";name=name.replace(/([A-Z])/g,"-$1").toLowerCase();var computedStyle=defaultView.getComputedStyle(elem,null);if(computedStyle&&!color(elem))ret=computedStyle.getPropertyValue(name);else{var swap=[],stack=[],a=elem,i=0;for(;a&&color(a);a=a.parentNode)stack.unshift(a);for(;i]*?)\/>/g,function(all,front,tag){return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?all:front+">";});var tags=jQuery.trim(elem).toLowerCase(),div=context.createElement("div");var wrap=!tags.indexOf("",""]||!tags.indexOf("",""]||tags.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
"]||!tags.indexOf("",""]||(!tags.indexOf("",""]||!tags.indexOf("",""]||jQuery.browser.msie&&[1,"div
","
"]||[0,"",""];div.innerHTML=wrap[1]+elem+wrap[2];while(wrap[0]--)div=div.lastChild;if(jQuery.browser.msie){var tbody=!tags.indexOf(""&&tags.indexOf("=0;--j)if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length)tbody[j].parentNode.removeChild(tbody[j]);if(/^\s/.test(elem))div.insertBefore(context.createTextNode(elem.match(/^\s*/)[0]),div.firstChild);}elem=jQuery.makeArray(div.childNodes);}if(elem.length===0&&(!jQuery.nodeName(elem,"form")&&!jQuery.nodeName(elem,"select")))return;if(elem[0]==undefined||jQuery.nodeName(elem,"form")||elem.options)ret.push(elem);else -ret=jQuery.merge(ret,elem);});return ret;},attr:function(elem,name,value){if(!elem||elem.nodeType==3||elem.nodeType==8)return undefined;var notxml=!jQuery.isXMLDoc(elem),set=value!==undefined,msie=jQuery.browser.msie;name=notxml&&jQuery.props[name]||name;if(elem.tagName){var special=/href|src|style/.test(name);if(name=="selected"&&jQuery.browser.safari)elem.parentNode.selectedIndex;if(name in elem&¬xml&&!special){if(set){if(name=="type"&&jQuery.nodeName(elem,"input")&&elem.parentNode)throw"type property can't be changed";elem[name]=value;}if(jQuery.nodeName(elem,"form")&&elem.getAttributeNode(name))return elem.getAttributeNode(name).nodeValue;return elem[name];}if(msie&¬xml&&name=="style")return jQuery.attr(elem.style,"cssText",value);if(set)elem.setAttribute(name,""+value);var attr=msie&¬xml&&special?elem.getAttribute(name,2):elem.getAttribute(name);return attr===null?undefined:attr;}if(msie&&name=="opacity"){if(set){elem.zoom=1;elem.filter=(elem.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(value)+''=="NaN"?"":"alpha(opacity="+value*100+")");}return elem.filter&&elem.filter.indexOf("opacity=")>=0?(parseFloat(elem.filter.match(/opacity=([^)]*)/)[1])/100)+'':"";}name=name.replace(/-([a-z])/ig,function(all,letter){return letter.toUpperCase();});if(set)elem[name]=value;return elem[name];},trim:function(text){return(text||"").replace(/^\s+|\s+$/g,"");},makeArray:function(array){var ret=[];if(array!=null){var i=array.length;if(i==null||array.split||array.setInterval||array.call)ret[0]=array;else -while(i)ret[--i]=array[i];}return ret;},inArray:function(elem,array){for(var i=0,length=array.length;i*",this).remove();while(this.firstChild)this.removeChild(this.firstChild);}},function(name,fn){jQuery.fn[name]=function(){return this.each(fn,arguments);};});jQuery.each(["Height","Width"],function(i,name){var type=name.toLowerCase();jQuery.fn[type]=function(size){return this[0]==window?jQuery.browser.opera&&document.body["client"+name]||jQuery.browser.safari&&window["inner"+name]||document.compatMode=="CSS1Compat"&&document.documentElement["client"+name]||document.body["client"+name]:this[0]==document?Math.max(Math.max(document.body["scroll"+name],document.documentElement["scroll"+name]),Math.max(document.body["offset"+name],document.documentElement["offset"+name])):size==undefined?(this.length?jQuery.css(this[0],type):null):this.css(type,size.constructor==String?size:size+"px");};});function num(elem,prop){return elem[0]&&parseInt(jQuery.curCSS(elem[0],prop,true),10)||0;}var chars=jQuery.browser.safari&&parseInt(jQuery.browser.version)<417?"(?:[\\w*_-]|\\\\.)":"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",quickChild=new RegExp("^>\\s*("+chars+"+)"),quickID=new RegExp("^("+chars+"+)(#)("+chars+"+)"),quickClass=new RegExp("^([#.]?)("+chars+"*)");jQuery.extend({expr:{"":function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},"#":function(a,i,m){return a.getAttribute("id")==m[2];},":":{lt:function(a,i,m){return im[3]-0;},nth:function(a,i,m){return m[3]-0==i;},eq:function(a,i,m){return m[3]-0==i;},first:function(a,i){return i==0;},last:function(a,i,m,r){return i==r.length-1;},even:function(a,i){return i%2==0;},odd:function(a,i){return i%2;},"first-child":function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},"last-child":function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},"only-child":function(a){return!jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},parent:function(a){return a.firstChild;},empty:function(a){return!a.firstChild;},contains:function(a,i,m){return(a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},visible:function(a){return"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},hidden:function(a){return"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},enabled:function(a){return!a.disabled;},disabled:function(a){return a.disabled;},checked:function(a){return a.checked;},selected:function(a){return a.selected||jQuery.attr(a,"selected");},text:function(a){return"text"==a.type;},radio:function(a){return"radio"==a.type;},checkbox:function(a){return"checkbox"==a.type;},file:function(a){return"file"==a.type;},password:function(a){return"password"==a.type;},submit:function(a){return"submit"==a.type;},image:function(a){return"image"==a.type;},reset:function(a){return"reset"==a.type;},button:function(a){return"button"==a.type||jQuery.nodeName(a,"button");},input:function(a){return/input|select|textarea|button/i.test(a.nodeName);},has:function(a,i,m){return jQuery.find(m[3],a).length;},header:function(a){return/h\d/i.test(a.nodeName);},animated:function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}}},parse:[/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,new RegExp("^([:.#]*)("+chars+"+)")],multiFilter:function(expr,elems,not){var old,cur=[];while(expr&&expr!=old){old=expr;var f=jQuery.filter(expr,elems,not);expr=f.t.replace(/^\s*,\s*/,"");cur=not?elems=f.r:jQuery.merge(cur,f.r);}return cur;},find:function(t,context){if(typeof t!="string")return[t];if(context&&context.nodeType!=1&&context.nodeType!=9)return[];context=context||document;var ret=[context],done=[],last,nodeName;while(t&&last!=t){var r=[];last=t;t=jQuery.trim(t);var foundToken=false,re=quickChild,m=re.exec(t);if(m){nodeName=m[1].toUpperCase();for(var i=0;ret[i];i++)for(var c=ret[i].firstChild;c;c=c.nextSibling)if(c.nodeType==1&&(nodeName=="*"||c.nodeName.toUpperCase()==nodeName))r.push(c);ret=r;t=t.replace(re,"");if(t.indexOf(" ")==0)continue;foundToken=true;}else{re=/^([>+~])\s*(\w*)/i;if((m=re.exec(t))!=null){r=[];var merge={};nodeName=m[2].toUpperCase();m=m[1];for(var j=0,rl=ret.length;j=0;if(!not&&pass||not&&!pass)tmp.push(r[i]);}return tmp;},filter:function(t,r,not){var last;while(t&&t!=last){last=t;var p=jQuery.parse,m;for(var i=0;p[i];i++){m=p[i].exec(t);if(m){t=t.substring(m[0].length);m[2]=m[2].replace(/\\/g,"");break;}}if(!m)break;if(m[1]==":"&&m[2]=="not")r=isSimple.test(m[3])?jQuery.filter(m[3],r,true).r:jQuery(r).not(m[3]);else if(m[1]==".")r=jQuery.classFilter(r,m[2],not);else if(m[1]=="["){var tmp=[],type=m[3];for(var i=0,rl=r.length;i=0)^not)tmp.push(a);}r=tmp;}else if(m[1]==":"&&m[2]=="nth-child"){var merge={},tmp=[],test=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(m[3]=="even"&&"2n"||m[3]=="odd"&&"2n+1"||!/\D/.test(m[3])&&"0n+"+m[3]||m[3]),first=(test[1]+(test[2]||1))-0,last=test[3]-0;for(var i=0,rl=r.length;i=0)add=true;if(add^not)tmp.push(node);}r=tmp;}else{var fn=jQuery.expr[m[1]];if(typeof fn=="object")fn=fn[m[2]];if(typeof fn=="string")fn=eval("false||function(a,i){return "+fn+";}");r=jQuery.grep(r,function(elem,i){return fn(elem,i,m,r);},not);}}return{r:r,t:t};},dir:function(elem,dir){var matched=[],cur=elem[dir];while(cur&&cur!=document){if(cur.nodeType==1)matched.push(cur);cur=cur[dir];}return matched;},nth:function(cur,result,dir,elem){result=result||1;var num=0;for(;cur;cur=cur[dir])if(cur.nodeType==1&&++num==result)break;return cur;},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType==1&&n!=elem)r.push(n);}return r;}});jQuery.event={add:function(elem,types,handler,data){if(elem.nodeType==3||elem.nodeType==8)return;if(jQuery.browser.msie&&elem.setInterval)elem=window;if(!handler.guid)handler.guid=this.guid++;if(data!=undefined){var fn=handler;handler=this.proxy(fn,function(){return fn.apply(this,arguments);});handler.data=data;}var events=jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),handle=jQuery.data(elem,"handle")||jQuery.data(elem,"handle",function(){if(typeof jQuery!="undefined"&&!jQuery.event.triggered)return jQuery.event.handle.apply(arguments.callee.elem,arguments);});handle.elem=elem;jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];handler.type=parts[1];var handlers=events[type];if(!handlers){handlers=events[type]={};if(!jQuery.event.special[type]||jQuery.event.special[type].setup.call(elem)===false){if(elem.addEventListener)elem.addEventListener(type,handle,false);else if(elem.attachEvent)elem.attachEvent("on"+type,handle);}}handlers[handler.guid]=handler;jQuery.event.global[type]=true;});elem=null;},guid:1,global:{},remove:function(elem,types,handler){if(elem.nodeType==3||elem.nodeType==8)return;var events=jQuery.data(elem,"events"),ret,index;if(events){if(types==undefined||(typeof types=="string"&&types.charAt(0)=="."))for(var type in events)this.remove(elem,type+(types||""));else{if(types.type){handler=types.handler;types=types.type;}jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];if(events[type]){if(handler)delete events[type][handler.guid];else -for(handler in events[type])if(!parts[1]||events[type][handler].type==parts[1])delete events[type][handler];for(ret in events[type])break;if(!ret){if(!jQuery.event.special[type]||jQuery.event.special[type].teardown.call(elem)===false){if(elem.removeEventListener)elem.removeEventListener(type,jQuery.data(elem,"handle"),false);else if(elem.detachEvent)elem.detachEvent("on"+type,jQuery.data(elem,"handle"));}ret=null;delete events[type];}}});}for(ret in events)break;if(!ret){var handle=jQuery.data(elem,"handle");if(handle)handle.elem=null;jQuery.removeData(elem,"events");jQuery.removeData(elem,"handle");}}},trigger:function(type,data,elem,donative,extra){data=jQuery.makeArray(data);if(type.indexOf("!")>=0){type=type.slice(0,-1);var exclusive=true;}if(!elem){if(this.global[type])jQuery("*").add([window,document]).trigger(type,data);}else{if(elem.nodeType==3||elem.nodeType==8)return undefined;var val,ret,fn=jQuery.isFunction(elem[type]||null),event=!data[0]||!data[0].preventDefault;if(event){data.unshift({type:type,target:elem,preventDefault:function(){},stopPropagation:function(){},timeStamp:now()});data[0][expando]=true;}data[0].type=type;if(exclusive)data[0].exclusive=true;var handle=jQuery.data(elem,"handle");if(handle)val=handle.apply(elem,data);if((!fn||(jQuery.nodeName(elem,'a')&&type=="click"))&&elem["on"+type]&&elem["on"+type].apply(elem,data)===false)val=false;if(event)data.shift();if(extra&&jQuery.isFunction(extra)){ret=extra.apply(elem,val==null?data:data.concat(val));if(ret!==undefined)val=ret;}if(fn&&donative!==false&&val!==false&&!(jQuery.nodeName(elem,'a')&&type=="click")){this.triggered=true;try{elem[type]();}catch(e){}}this.triggered=false;}return val;},handle:function(event){var val,ret,namespace,all,handlers;event=arguments[0]=jQuery.event.fix(event||window.event);namespace=event.type.split(".");event.type=namespace[0];namespace=namespace[1];all=!namespace&&!event.exclusive;handlers=(jQuery.data(this,"events")||{})[event.type];for(var j in handlers){var handler=handlers[j];if(all||handler.type==namespace){event.handler=handler;event.data=handler.data;ret=handler.apply(this,arguments);if(val!==false)val=ret;if(ret===false){event.preventDefault();event.stopPropagation();}}}return val;},fix:function(event){if(event[expando]==true)return event;var originalEvent=event;event={originalEvent:originalEvent};var props="altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target timeStamp toElement type view wheelDelta which".split(" ");for(var i=props.length;i;i--)event[props[i]]=originalEvent[props[i]];event[expando]=true;event.preventDefault=function(){if(originalEvent.preventDefault)originalEvent.preventDefault();originalEvent.returnValue=false;};event.stopPropagation=function(){if(originalEvent.stopPropagation)originalEvent.stopPropagation();originalEvent.cancelBubble=true;};event.timeStamp=event.timeStamp||now();if(!event.target)event.target=event.srcElement||document;if(event.target.nodeType==3)event.target=event.target.parentNode;if(!event.relatedTarget&&event.fromElement)event.relatedTarget=event.fromElement==event.target?event.toElement:event.fromElement;if(event.pageX==null&&event.clientX!=null){var doc=document.documentElement,body=document.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc.clientTop||0);}if(!event.which&&((event.charCode||event.charCode===0)?event.charCode:event.keyCode))event.which=event.charCode||event.keyCode;if(!event.metaKey&&event.ctrlKey)event.metaKey=event.ctrlKey;if(!event.which&&event.button)event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)));return event;},proxy:function(fn,proxy){proxy.guid=fn.guid=fn.guid||proxy.guid||this.guid++;return proxy;},special:{ready:{setup:function(){bindReady();return;},teardown:function(){return;}},mouseenter:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseover",jQuery.event.special.mouseenter.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseover",jQuery.event.special.mouseenter.handler);return true;},handler:function(event){if(withinElement(event,this))return true;event.type="mouseenter";return jQuery.event.handle.apply(this,arguments);}},mouseleave:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseout",jQuery.event.special.mouseleave.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseout",jQuery.event.special.mouseleave.handler);return true;},handler:function(event){if(withinElement(event,this))return true;event.type="mouseleave";return jQuery.event.handle.apply(this,arguments);}}}};jQuery.fn.extend({bind:function(type,data,fn){return type=="unload"?this.one(type,data,fn):this.each(function(){jQuery.event.add(this,type,fn||data,fn&&data);});},one:function(type,data,fn){var one=jQuery.event.proxy(fn||data,function(event){jQuery(this).unbind(event,one);return(fn||data).apply(this,arguments);});return this.each(function(){jQuery.event.add(this,type,one,fn&&data);});},unbind:function(type,fn){return this.each(function(){jQuery.event.remove(this,type,fn);});},trigger:function(type,data,fn){return this.each(function(){jQuery.event.trigger(type,data,this,true,fn);});},triggerHandler:function(type,data,fn){return this[0]&&jQuery.event.trigger(type,data,this[0],false,fn);},toggle:function(fn){var args=arguments,i=1;while(i=0){var selector=url.slice(off,url.length);url=url.slice(0,off);}callback=callback||function(){};var type="GET";if(params)if(jQuery.isFunction(params)){callback=params;params=null;}else{params=jQuery.param(params);type="POST";}var self=this;jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(res,status){if(status=="success"||status=="notmodified")self.html(selector?jQuery("
").append(res.responseText.replace(//g,"")).find(selector):res.responseText);self.each(callback,[res.responseText,status,res]);}});return this;},serialize:function(){return jQuery.param(this.serializeArray());},serializeArray:function(){return this.map(function(){return jQuery.nodeName(this,"form")?jQuery.makeArray(this.elements):this;}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type));}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:val.constructor==Array?jQuery.map(val,function(val,i){return{name:elem.name,value:val};}):{name:elem.name,value:val};}).get();}});jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(i,o){jQuery.fn[o]=function(f){return this.bind(o,f);};});var jsc=now();jQuery.extend({get:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data=null;}return jQuery.ajax({type:"GET",url:url,data:data,success:callback,dataType:type});},getScript:function(url,callback){return jQuery.get(url,null,callback,"script");},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json");},post:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data={};}return jQuery.ajax({type:"POST",url:url,data:data,success:callback,dataType:type});},ajaxSetup:function(settings){jQuery.extend(jQuery.ajaxSettings,settings);},ajaxSettings:{url:location.href,global:true,type:"GET",timeout:0,contentType:"application/x-www-form-urlencoded",processData:true,async:true,data:null,username:null,password:null,accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(s){s=jQuery.extend(true,s,jQuery.extend(true,{},jQuery.ajaxSettings,s));var jsonp,jsre=/=\?(&|$)/g,status,data,type=s.type.toUpperCase();if(s.data&&s.processData&&typeof s.data!="string")s.data=jQuery.param(s.data);if(s.dataType=="jsonp"){if(type=="GET"){if(!s.url.match(jsre))s.url+=(s.url.match(/\?/)?"&":"?")+(s.jsonp||"callback")+"=?";}else if(!s.data||!s.data.match(jsre))s.data=(s.data?s.data+"&":"")+(s.jsonp||"callback")+"=?";s.dataType="json";}if(s.dataType=="json"&&(s.data&&s.data.match(jsre)||s.url.match(jsre))){jsonp="jsonp"+jsc++;if(s.data)s.data=(s.data+"").replace(jsre,"="+jsonp+"$1");s.url=s.url.replace(jsre,"="+jsonp+"$1");s.dataType="script";window[jsonp]=function(tmp){data=tmp;success();complete();window[jsonp]=undefined;try{delete window[jsonp];}catch(e){}if(head)head.removeChild(script);};}if(s.dataType=="script"&&s.cache==null)s.cache=false;if(s.cache===false&&type=="GET"){var ts=now();var ret=s.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+ts+"$2");s.url=ret+((ret==s.url)?(s.url.match(/\?/)?"&":"?")+"_="+ts:"");}if(s.data&&type=="GET"){s.url+=(s.url.match(/\?/)?"&":"?")+s.data;s.data=null;}if(s.global&&!jQuery.active++)jQuery.event.trigger("ajaxStart");var remote=/^(?:\w+:)?\/\/([^\/?#]+)/;if(s.dataType=="script"&&type=="GET"&&remote.test(s.url)&&remote.exec(s.url)[1]!=location.host){var head=document.getElementsByTagName("head")[0];var script=document.createElement("script");script.src=s.url;if(s.scriptCharset)script.charset=s.scriptCharset;if(!jsonp){var done=false;script.onload=script.onreadystatechange=function(){if(!done&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){done=true;success();complete();head.removeChild(script);}};}head.appendChild(script);return undefined;}var requestDone=false;var xhr=window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();if(s.username)xhr.open(type,s.url,s.async,s.username,s.password);else -xhr.open(type,s.url,s.async);try{if(s.data)xhr.setRequestHeader("Content-Type",s.contentType);if(s.ifModified)xhr.setRequestHeader("If-Modified-Since",jQuery.lastModified[s.url]||"Thu, 01 Jan 1970 00:00:00 GMT");xhr.setRequestHeader("X-Requested-With","XMLHttpRequest");xhr.setRequestHeader("Accept",s.dataType&&s.accepts[s.dataType]?s.accepts[s.dataType]+", */*":s.accepts._default);}catch(e){}if(s.beforeSend&&s.beforeSend(xhr,s)===false){s.global&&jQuery.active--;xhr.abort();return false;}if(s.global)jQuery.event.trigger("ajaxSend",[xhr,s]);var onreadystatechange=function(isTimeout){if(!requestDone&&xhr&&(xhr.readyState==4||isTimeout=="timeout")){requestDone=true;if(ival){clearInterval(ival);ival=null;}status=isTimeout=="timeout"&&"timeout"||!jQuery.httpSuccess(xhr)&&"error"||s.ifModified&&jQuery.httpNotModified(xhr,s.url)&&"notmodified"||"success";if(status=="success"){try{data=jQuery.httpData(xhr,s.dataType,s.dataFilter);}catch(e){status="parsererror";}}if(status=="success"){var modRes;try{modRes=xhr.getResponseHeader("Last-Modified");}catch(e){}if(s.ifModified&&modRes)jQuery.lastModified[s.url]=modRes;if(!jsonp)success();}else -jQuery.handleError(s,xhr,status);complete();if(s.async)xhr=null;}};if(s.async){var ival=setInterval(onreadystatechange,13);if(s.timeout>0)setTimeout(function(){if(xhr){xhr.abort();if(!requestDone)onreadystatechange("timeout");}},s.timeout);}try{xhr.send(s.data);}catch(e){jQuery.handleError(s,xhr,null,e);}if(!s.async)onreadystatechange();function success(){if(s.success)s.success(data,status);if(s.global)jQuery.event.trigger("ajaxSuccess",[xhr,s]);}function complete(){if(s.complete)s.complete(xhr,status);if(s.global)jQuery.event.trigger("ajaxComplete",[xhr,s]);if(s.global&&!--jQuery.active)jQuery.event.trigger("ajaxStop");}return xhr;},handleError:function(s,xhr,status,e){if(s.error)s.error(xhr,status,e);if(s.global)jQuery.event.trigger("ajaxError",[xhr,s,e]);},active:0,httpSuccess:function(xhr){try{return!xhr.status&&location.protocol=="file:"||(xhr.status>=200&&xhr.status<300)||xhr.status==304||xhr.status==1223||jQuery.browser.safari&&xhr.status==undefined;}catch(e){}return false;},httpNotModified:function(xhr,url){try{var xhrRes=xhr.getResponseHeader("Last-Modified");return xhr.status==304||xhrRes==jQuery.lastModified[url]||jQuery.browser.safari&&xhr.status==undefined;}catch(e){}return false;},httpData:function(xhr,type,filter){var ct=xhr.getResponseHeader("content-type"),xml=type=="xml"||!type&&ct&&ct.indexOf("xml")>=0,data=xml?xhr.responseXML:xhr.responseText;if(xml&&data.documentElement.tagName=="parsererror")throw"parsererror";if(filter)data=filter(data,type);if(type=="script")jQuery.globalEval(data);if(type=="json")data=eval("("+data+")");return data;},param:function(a){var s=[];if(a.constructor==Array||a.jquery)jQuery.each(a,function(){s.push(encodeURIComponent(this.name)+"="+encodeURIComponent(this.value));});else -for(var j in a)if(a[j]&&a[j].constructor==Array)jQuery.each(a[j],function(){s.push(encodeURIComponent(j)+"="+encodeURIComponent(this));});else -s.push(encodeURIComponent(j)+"="+encodeURIComponent(jQuery.isFunction(a[j])?a[j]():a[j]));return s.join("&").replace(/%20/g,"+");}});jQuery.fn.extend({show:function(speed,callback){return speed?this.animate({height:"show",width:"show",opacity:"show"},speed,callback):this.filter(":hidden").each(function(){this.style.display=this.oldblock||"";if(jQuery.css(this,"display")=="none"){var elem=jQuery("<"+this.tagName+" />").appendTo("body");this.style.display=elem.css("display");if(this.style.display=="none")this.style.display="block";elem.remove();}}).end();},hide:function(speed,callback){return speed?this.animate({height:"hide",width:"hide",opacity:"hide"},speed,callback):this.filter(":visible").each(function(){this.oldblock=this.oldblock||jQuery.css(this,"display");this.style.display="none";}).end();},_toggle:jQuery.fn.toggle,toggle:function(fn,fn2){return jQuery.isFunction(fn)&&jQuery.isFunction(fn2)?this._toggle.apply(this,arguments):fn?this.animate({height:"toggle",width:"toggle",opacity:"toggle"},fn,fn2):this.each(function(){jQuery(this)[jQuery(this).is(":hidden")?"show":"hide"]();});},slideDown:function(speed,callback){return this.animate({height:"show"},speed,callback);},slideUp:function(speed,callback){return this.animate({height:"hide"},speed,callback);},slideToggle:function(speed,callback){return this.animate({height:"toggle"},speed,callback);},fadeIn:function(speed,callback){return this.animate({opacity:"show"},speed,callback);},fadeOut:function(speed,callback){return this.animate({opacity:"hide"},speed,callback);},fadeTo:function(speed,to,callback){return this.animate({opacity:to},speed,callback);},animate:function(prop,speed,easing,callback){var optall=jQuery.speed(speed,easing,callback);return this[optall.queue===false?"each":"queue"](function(){if(this.nodeType!=1)return false;var opt=jQuery.extend({},optall),p,hidden=jQuery(this).is(":hidden"),self=this;for(p in prop){if(prop[p]=="hide"&&hidden||prop[p]=="show"&&!hidden)return opt.complete.call(this);if(p=="height"||p=="width"){opt.display=jQuery.css(this,"display");opt.overflow=this.style.overflow;}}if(opt.overflow!=null)this.style.overflow="hidden";opt.curAnim=jQuery.extend({},prop);jQuery.each(prop,function(name,val){var e=new jQuery.fx(self,opt,name);if(/toggle|show|hide/.test(val))e[val=="toggle"?hidden?"show":"hide":val](prop);else{var parts=val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),start=e.cur(true)||0;if(parts){var end=parseFloat(parts[2]),unit=parts[3]||"px";if(unit!="px"){self.style[name]=(end||1)+unit;start=((end||1)/e.cur(true))*start;self.style[name]=start+unit;}if(parts[1])end=((parts[1]=="-="?-1:1)*end)+start;e.custom(start,end,unit);}else -e.custom(start,val,"");}});return true;});},queue:function(type,fn){if(jQuery.isFunction(type)||(type&&type.constructor==Array)){fn=type;type="fx";}if(!type||(typeof type=="string"&&!fn))return queue(this[0],type);return this.each(function(){if(fn.constructor==Array)queue(this,type,fn);else{queue(this,type).push(fn);if(queue(this,type).length==1)fn.call(this);}});},stop:function(clearQueue,gotoEnd){var timers=jQuery.timers;if(clearQueue)this.queue([]);this.each(function(){for(var i=timers.length-1;i>=0;i--)if(timers[i].elem==this){if(gotoEnd)timers[i](true);timers.splice(i,1);}});if(!gotoEnd)this.dequeue();return this;}});var queue=function(elem,type,array){if(elem){type=type||"fx";var q=jQuery.data(elem,type+"queue");if(!q||array)q=jQuery.data(elem,type+"queue",jQuery.makeArray(array));}return q;};jQuery.fn.dequeue=function(type){type=type||"fx";return this.each(function(){var q=queue(this,type);q.shift();if(q.length)q[0].call(this);});};jQuery.extend({speed:function(speed,easing,fn){var opt=speed&&speed.constructor==Object?speed:{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&easing.constructor!=Function&&easing};opt.duration=(opt.duration&&opt.duration.constructor==Number?opt.duration:jQuery.fx.speeds[opt.duration])||jQuery.fx.speeds.def;opt.old=opt.complete;opt.complete=function(){if(opt.queue!==false)jQuery(this).dequeue();if(jQuery.isFunction(opt.old))opt.old.call(this);};return opt;},easing:{linear:function(p,n,firstNum,diff){return firstNum+diff*p;},swing:function(p,n,firstNum,diff){return((-Math.cos(p*Math.PI)/2)+0.5)*diff+firstNum;}},timers:[],timerId:null,fx:function(elem,options,prop){this.options=options;this.elem=elem;this.prop=prop;if(!options.orig)options.orig={};}});jQuery.fx.prototype={update:function(){if(this.options.step)this.options.step.call(this.elem,this.now,this);(jQuery.fx.step[this.prop]||jQuery.fx.step._default)(this);if(this.prop=="height"||this.prop=="width")this.elem.style.display="block";},cur:function(force){if(this.elem[this.prop]!=null&&this.elem.style[this.prop]==null)return this.elem[this.prop];var r=parseFloat(jQuery.css(this.elem,this.prop,force));return r&&r>-10000?r:parseFloat(jQuery.curCSS(this.elem,this.prop))||0;},custom:function(from,to,unit){this.startTime=now();this.start=from;this.end=to;this.unit=unit||this.unit||"px";this.now=this.start;this.pos=this.state=0;this.update();var self=this;function t(gotoEnd){return self.step(gotoEnd);}t.elem=this.elem;jQuery.timers.push(t);if(jQuery.timerId==null){jQuery.timerId=setInterval(function(){var timers=jQuery.timers;for(var i=0;ithis.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var done=true;for(var i in this.options.curAnim)if(this.options.curAnim[i]!==true)done=false;if(done){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(jQuery.css(this.elem,"display")=="none")this.elem.style.display="block";}if(this.options.hide)this.elem.style.display="none";if(this.options.hide||this.options.show)for(var p in this.options.curAnim)jQuery.attr(this.elem.style,p,this.options.orig[p]);}if(done)this.options.complete.call(this.elem);return false;}else{var n=t-this.startTime;this.state=n/this.options.duration;this.pos=jQuery.easing[this.options.easing||(jQuery.easing.swing?"swing":"linear")](this.state,n,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update();}return true;}};jQuery.extend(jQuery.fx,{speeds:{slow:600,fast:200,def:400},step:{scrollLeft:function(fx){fx.elem.scrollLeft=fx.now;},scrollTop:function(fx){fx.elem.scrollTop=fx.now;},opacity:function(fx){jQuery.attr(fx.elem.style,"opacity",fx.now);},_default:function(fx){fx.elem.style[fx.prop]=fx.now+fx.unit;}}});jQuery.fn.offset=function(){var left=0,top=0,elem=this[0],results;if(elem)with(jQuery.browser){var parent=elem.parentNode,offsetChild=elem,offsetParent=elem.offsetParent,doc=elem.ownerDocument,safari2=safari&&parseInt(version)<522&&!/adobeair/i.test(userAgent),css=jQuery.curCSS,fixed=css(elem,"position")=="fixed";if(elem.getBoundingClientRect){var box=elem.getBoundingClientRect();add(box.left+Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),box.top+Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));add(-doc.documentElement.clientLeft,-doc.documentElement.clientTop);}else{add(elem.offsetLeft,elem.offsetTop);while(offsetParent){add(offsetParent.offsetLeft,offsetParent.offsetTop);if(mozilla&&!/^t(able|d|h)$/i.test(offsetParent.tagName)||safari&&!safari2)border(offsetParent);if(!fixed&&css(offsetParent,"position")=="fixed")fixed=true;offsetChild=/^body$/i.test(offsetParent.tagName)?offsetChild:offsetParent;offsetParent=offsetParent.offsetParent;}while(parent&&parent.tagName&&!/^body|html$/i.test(parent.tagName)){if(!/^inline|table.*$/i.test(css(parent,"display")))add(-parent.scrollLeft,-parent.scrollTop);if(mozilla&&css(parent,"overflow")!="visible")border(parent);parent=parent.parentNode;}if((safari2&&(fixed||css(offsetChild,"position")=="absolute"))||(mozilla&&css(offsetChild,"position")!="absolute"))add(-doc.body.offsetLeft,-doc.body.offsetTop);if(fixed)add(Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));}results={top:top,left:left};}function border(elem){add(jQuery.curCSS(elem,"borderLeftWidth",true),jQuery.curCSS(elem,"borderTopWidth",true));}function add(l,t){left+=parseInt(l,10)||0;top+=parseInt(t,10)||0;}return results;};jQuery.fn.extend({position:function(){var left=0,top=0,results;if(this[0]){var offsetParent=this.offsetParent(),offset=this.offset(),parentOffset=/^body|html$/i.test(offsetParent[0].tagName)?{top:0,left:0}:offsetParent.offset();offset.top-=num(this,'marginTop');offset.left-=num(this,'marginLeft');parentOffset.top+=num(offsetParent,'borderTopWidth');parentOffset.left+=num(offsetParent,'borderLeftWidth');results={top:offset.top-parentOffset.top,left:offset.left-parentOffset.left};}return results;},offsetParent:function(){var offsetParent=this[0].offsetParent;while(offsetParent&&(!/^body|html$/i.test(offsetParent.tagName)&&jQuery.css(offsetParent,'position')=='static'))offsetParent=offsetParent.offsetParent;return jQuery(offsetParent);}});jQuery.each(['Left','Top'],function(i,name){var method='scroll'+name;jQuery.fn[method]=function(val){if(!this[0])return;return val!=undefined?this.each(function(){this==window||this==document?window.scrollTo(!i?val:jQuery(window).scrollLeft(),i?val:jQuery(window).scrollTop()):this[method]=val;}):this[0]==window||this[0]==document?self[i?'pageYOffset':'pageXOffset']||jQuery.boxModel&&document.documentElement[method]||document.body[method]:this[0][method];};});jQuery.each(["Height","Width"],function(i,name){var tl=i?"Left":"Top",br=i?"Right":"Bottom";jQuery.fn["inner"+name]=function(){return this[name.toLowerCase()]()+num(this,"padding"+tl)+num(this,"padding"+br);};jQuery.fn["outer"+name]=function(margin){return this["inner"+name]()+num(this,"border"+tl+"Width")+num(this,"border"+br+"Width")+(margin?num(this,"margin"+tl)+num(this,"margin"+br):0);};});})(); \ No newline at end of file + +// Map over jQuery in case of overwrite +var _jQuery = window.jQuery, +// Map over the $ in case of overwrite + _$ = window.$; + +var jQuery = window.jQuery = window.$ = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context ); +}; + +// A simple way to check for HTML strings or ID strings +// (both of which we optimize for) +var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/, + +// Is it a simple selector + isSimple = /^.[^:#\[\.]*$/, + +// Will speed up references to undefined, and allows munging its name. + undefined; + +jQuery.fn = jQuery.prototype = { + init: function( selector, context ) { + // Make sure that a selection was provided + selector = selector || document; + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this[0] = selector; + this.length = 1; + return this; + } + // Handle HTML strings + if ( typeof selector == "string" ) { + // Are we dealing with HTML string or an ID? + var match = quickExpr.exec( selector ); + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) + selector = jQuery.clean( [ match[1] ], context ); + + // HANDLE: $("#id") + else { + var elem = document.getElementById( match[3] ); + + // Make sure an element was located + if ( elem ){ + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id != match[3] ) + return jQuery().find( selector ); + + // Otherwise, we inject the element directly into the jQuery object + return jQuery( elem ); + } + selector = []; + } + + // HANDLE: $(expr, [context]) + // (which is just equivalent to: $(content).find(expr) + } else + return jQuery( context ).find( selector ); + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) + return jQuery( document )[ jQuery.fn.ready ? "ready" : "load" ]( selector ); + + return this.setArray(jQuery.makeArray(selector)); + }, + + // The current version of jQuery being used + jquery: "1.2.6", + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + // The number of elements contained in the matched element set + length: 0, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == undefined ? + + // Return a 'clean' array + jQuery.makeArray( this ) : + + // Return just the object + this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + // Build a new jQuery matched element set + var ret = jQuery( elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Force the current matched set of elements to become + // the specified array of elements (destroying the stack in the process) + // You should use pushStack() in order to do this, but maintain the stack + setArray: function( elems ) { + // Resetting the length to 0, then using the native Array push + // is a super-fast way to populate an object with array-like properties + this.length = 0; + Array.prototype.push.apply( this, elems ); + + return this; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + var ret = -1; + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem && elem.jquery ? elem[0] : elem + , this ); + }, + + attr: function( name, value, type ) { + var options = name; + + // Look for the case where we're accessing a style value + if ( name.constructor == String ) + if ( value === undefined ) + return this[0] && jQuery[ type || "attr" ]( this[0], name ); + + else { + options = {}; + options[ name ] = value; + } + + // Check to see if we're setting style values + return this.each(function(i){ + // Set all the styles + for ( name in options ) + jQuery.attr( + type ? + this.style : + this, + name, jQuery.prop( this, options[ name ], type, i, name ) + ); + }); + }, + + css: function( key, value ) { + // ignore negative width and height values + if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 ) + value = undefined; + return this.attr( key, value, "curCSS" ); + }, + + text: function( text ) { + if ( typeof text != "object" && text != null ) + return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) ); + + var ret = ""; + + jQuery.each( text || this, function(){ + jQuery.each( this.childNodes, function(){ + if ( this.nodeType != 8 ) + ret += this.nodeType != 1 ? + this.nodeValue : + jQuery.fn.text( [ this ] ); + }); + }); + + return ret; + }, + + wrapAll: function( html ) { + if ( this[0] ) + // The elements to wrap the target around + jQuery( html, this[0].ownerDocument ) + .clone() + .insertBefore( this[0] ) + .map(function(){ + var elem = this; + + while ( elem.firstChild ) + elem = elem.firstChild; + + return elem; + }) + .append(this); + + return this; + }, + + wrapInner: function( html ) { + return this.each(function(){ + jQuery( this ).contents().wrapAll( html ); + }); + }, + + wrap: function( html ) { + return this.each(function(){ + jQuery( this ).wrapAll( html ); + }); + }, + + append: function() { + return this.domManip(arguments, true, false, function(elem){ + if (this.nodeType == 1) + this.appendChild( elem ); + }); + }, + + prepend: function() { + return this.domManip(arguments, true, true, function(elem){ + if (this.nodeType == 1) + this.insertBefore( elem, this.firstChild ); + }); + }, + + before: function() { + return this.domManip(arguments, false, false, function(elem){ + this.parentNode.insertBefore( elem, this ); + }); + }, + + after: function() { + return this.domManip(arguments, false, true, function(elem){ + this.parentNode.insertBefore( elem, this.nextSibling ); + }); + }, + + end: function() { + return this.prevObject || jQuery( [] ); + }, + + find: function( selector ) { + var elems = jQuery.map(this, function(elem){ + return jQuery.find( selector, elem ); + }); + + return this.pushStack( /[^+>] [^+>]/.test( selector ) || selector.indexOf("..") > -1 ? + jQuery.unique( elems ) : + elems ); + }, + + clone: function( events ) { + // Do the clone + var ret = this.map(function(){ + if ( jQuery.browser.msie && !jQuery.isXMLDoc(this) ) { + // IE copies events bound via attachEvent when + // using cloneNode. Calling detachEvent on the + // clone will also remove the events from the orignal + // In order to get around this, we use innerHTML. + // Unfortunately, this means some modifications to + // attributes in IE that are actually only stored + // as properties will not be copied (such as the + // the name attribute on an input). + var clone = this.cloneNode(true), + container = document.createElement("div"); + container.appendChild(clone); + return jQuery.clean([container.innerHTML])[0]; + } else + return this.cloneNode(true); + }); + + // Need to set the expando to null on the cloned set if it exists + // removeData doesn't work here, IE removes it from the original as well + // this is primarily for IE but the data expando shouldn't be copied over in any browser + var clone = ret.find("*").andSelf().each(function(){ + if ( this[ expando ] != undefined ) + this[ expando ] = null; + }); + + // Copy the events from the original to the clone + if ( events === true ) + this.find("*").andSelf().each(function(i){ + if (this.nodeType == 3) + return; + var events = jQuery.data( this, "events" ); + + for ( var type in events ) + for ( var handler in events[ type ] ) + jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data ); + }); + + // Return the cloned set + return ret; + }, + + filter: function( selector ) { + return this.pushStack( + jQuery.isFunction( selector ) && + jQuery.grep(this, function(elem, i){ + return selector.call( elem, i ); + }) || + + jQuery.multiFilter( selector, this ) ); + }, + + not: function( selector ) { + if ( selector.constructor == String ) + // test special case where just one selector is passed in + if ( isSimple.test( selector ) ) + return this.pushStack( jQuery.multiFilter( selector, this, true ) ); + else + selector = jQuery.multiFilter( selector, this ); + + var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType; + return this.filter(function() { + return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector; + }); + }, + + add: function( selector ) { + return this.pushStack( jQuery.unique( jQuery.merge( + this.get(), + typeof selector == 'string' ? + jQuery( selector ) : + jQuery.makeArray( selector ) + ))); + }, + + is: function( selector ) { + return !!selector && jQuery.multiFilter( selector, this ).length > 0; + }, + + hasClass: function( selector ) { + return this.is( "." + selector ); + }, + + val: function( value ) { + if ( value == undefined ) { + + if ( this.length ) { + var elem = this[0]; + + // We need to handle select boxes special + if ( jQuery.nodeName( elem, "select" ) ) { + var index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type == "select-one"; + + // Nothing was selected + if ( index < 0 ) + return null; + + // Loop through all the selected options + for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { + var option = options[ i ]; + + if ( option.selected ) { + // Get the specifc value for the option + value = jQuery.browser.msie && !option.attributes.value.specified ? option.text : option.value; + + // We don't need an array for one selects + if ( one ) + return value; + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + + // Everything else, we just grab the value + } else + return (this[0].value || "").replace(/\r/g, ""); + + } + + return undefined; + } + + if( value.constructor == Number ) + value += ''; + + return this.each(function(){ + if ( this.nodeType != 1 ) + return; + + if ( value.constructor == Array && /radio|checkbox/.test( this.type ) ) + this.checked = (jQuery.inArray(this.value, value) >= 0 || + jQuery.inArray(this.name, value) >= 0); + + else if ( jQuery.nodeName( this, "select" ) ) { + var values = jQuery.makeArray(value); + + jQuery( "option", this ).each(function(){ + this.selected = (jQuery.inArray( this.value, values ) >= 0 || + jQuery.inArray( this.text, values ) >= 0); + }); + + if ( !values.length ) + this.selectedIndex = -1; + + } else + this.value = value; + }); + }, + + html: function( value ) { + return value == undefined ? + (this[0] ? + this[0].innerHTML : + null) : + this.empty().append( value ); + }, + + replaceWith: function( value ) { + return this.after( value ).remove(); + }, + + eq: function( i ) { + return this.slice( i, i + 1 ); + }, + + slice: function() { + return this.pushStack( Array.prototype.slice.apply( this, arguments ) ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function(elem, i){ + return callback.call( elem, i, elem ); + })); + }, + + andSelf: function() { + return this.add( this.prevObject ); + }, + + data: function( key, value ){ + var parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value === undefined ) { + var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + if ( data === undefined && this.length ) + data = jQuery.data( this[0], key ); + + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + } else + return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){ + jQuery.data( this, key, value ); + }); + }, + + removeData: function( key ){ + return this.each(function(){ + jQuery.removeData( this, key ); + }); + }, + + domManip: function( args, table, reverse, callback ) { + var clone = this.length > 1, elems; + + return this.each(function(){ + if ( !elems ) { + elems = jQuery.clean( args, this.ownerDocument ); + + if ( reverse ) + elems.reverse(); + } + + var obj = this; + + if ( table && jQuery.nodeName( this, "table" ) && jQuery.nodeName( elems[0], "tr" ) ) + obj = this.getElementsByTagName("tbody")[0] || this.appendChild( this.ownerDocument.createElement("tbody") ); + + var scripts = jQuery( [] ); + + jQuery.each(elems, function(){ + var elem = clone ? + jQuery( this ).clone( true )[0] : + this; + + // execute all scripts after the elements have been injected + if ( jQuery.nodeName( elem, "script" ) ) + scripts = scripts.add( elem ); + else { + // Remove any inner scripts for later evaluation + if ( elem.nodeType == 1 ) + scripts = scripts.add( jQuery( "script", elem ).remove() ); + + // Inject the elements into the document + callback.call( obj, elem ); + } + }); + + scripts.each( evalScript ); + }); + } +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +function evalScript( i, elem ) { + if ( elem.src ) + jQuery.ajax({ + url: elem.src, + async: false, + dataType: "script" + }); + + else + jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" ); + + if ( elem.parentNode ) + elem.parentNode.removeChild( elem ); +} + +function now(){ + return +new Date; +} + +jQuery.extend = jQuery.fn.extend = function() { + // copy reference to target object + var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options; + + // Handle a deep copy situation + if ( target.constructor == Boolean ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target != "object" && typeof target != "function" ) + target = {}; + + // extend jQuery itself if only one argument is passed + if ( length == i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) + // Extend the base object + for ( var name in options ) { + var src = target[ name ], copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) + continue; + + // Recurse if we're merging object values + if ( deep && copy && typeof copy == "object" && !copy.nodeType ) + target[ name ] = jQuery.extend( deep, + // Never move original objects, clone them + src || ( copy.length != null ? [ ] : { } ) + , copy ); + + // Don't bring in undefined values + else if ( copy !== undefined ) + target[ name ] = copy; + + } + + // Return the modified object + return target; +}; + +var expando = "jQuery" + now(), uuid = 0, windowData = {}, + // exclude the following css properties to add px + exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i, + // cache defaultView + defaultView = document.defaultView || {}; + +jQuery.extend({ + noConflict: function( deep ) { + window.$ = _$; + + if ( deep ) + window.jQuery = _jQuery; + + return jQuery; + }, + + // See test/unit/core.js for details concerning this function. + isFunction: function( fn ) { + return !!fn && typeof fn != "string" && !fn.nodeName && + fn.constructor != Array && /^[\s[]?function/.test( fn + "" ); + }, + + // check if an element is in a (or is an) XML document + isXMLDoc: function( elem ) { + return elem.documentElement && !elem.body || + elem.tagName && elem.ownerDocument && !elem.ownerDocument.body; + }, + + // Evalulates a script in a global context + globalEval: function( data ) { + data = jQuery.trim( data ); + + if ( data ) { + // Inspired by code by Andrea Giammarchi + // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html + var head = document.getElementsByTagName("head")[0] || document.documentElement, + script = document.createElement("script"); + + script.type = "text/javascript"; + if ( jQuery.browser.msie ) + script.text = data; + else + script.appendChild( document.createTextNode( data ) ); + + // Use insertBefore instead of appendChild to circumvent an IE6 bug. + // This arises when a base node is used (#2709). + head.insertBefore( script, head.firstChild ); + head.removeChild( script ); + } + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase(); + }, + + cache: {}, + + data: function( elem, name, data ) { + elem = elem == window ? + windowData : + elem; + + var id = elem[ expando ]; + + // Compute a unique ID for the element + if ( !id ) + id = elem[ expando ] = ++uuid; + + // Only generate the data cache if we're + // trying to access or manipulate it + if ( name && !jQuery.cache[ id ] ) + jQuery.cache[ id ] = {}; + + // Prevent overriding the named cache with undefined values + if ( data !== undefined ) + jQuery.cache[ id ][ name ] = data; + + // Return the named cache data, or the ID for the element + return name ? + jQuery.cache[ id ][ name ] : + id; + }, + + removeData: function( elem, name ) { + elem = elem == window ? + windowData : + elem; + + var id = elem[ expando ]; + + // If we want to remove a specific section of the element's data + if ( name ) { + if ( jQuery.cache[ id ] ) { + // Remove the section of cache data + delete jQuery.cache[ id ][ name ]; + + // If we've removed all the data, remove the element's cache + name = ""; + + for ( name in jQuery.cache[ id ] ) + break; + + if ( !name ) + jQuery.removeData( elem ); + } + + // Otherwise, we want to remove all of the element's data + } else { + // Clean up the element expando + try { + delete elem[ expando ]; + } catch(e){ + // IE has trouble directly removing the expando + // but it's ok with using removeAttribute + if ( elem.removeAttribute ) + elem.removeAttribute( expando ); + } + + // Completely remove the data cache + delete jQuery.cache[ id ]; + } + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, length = object.length; + + if ( args ) { + if ( length == undefined ) { + for ( name in object ) + if ( callback.apply( object[ name ], args ) === false ) + break; + } else + for ( ; i < length; ) + if ( callback.apply( object[ i++ ], args ) === false ) + break; + + // A special, fast, case for the most common use of each + } else { + if ( length == undefined ) { + for ( name in object ) + if ( callback.call( object[ name ], name, object[ name ] ) === false ) + break; + } else + for ( var value = object[0]; + i < length && callback.call( value, i, value ) !== false; value = object[++i] ){} + } + + return object; + }, + + prop: function( elem, value, type, i, name ) { + // Handle executable functions + if ( jQuery.isFunction( value ) ) + value = value.call( elem, i ); + + // Handle passing in a number to a CSS property + return value && value.constructor == Number && type == "curCSS" && !exclude.test( name ) ? + value + "px" : + value; + }, + + className: { + // internal only, use addClass("class") + add: function( elem, classNames ) { + jQuery.each((classNames || "").split(/\s+/), function(i, className){ + if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) ) + elem.className += (elem.className ? " " : "") + className; + }); + }, + + // internal only, use removeClass("class") + remove: function( elem, classNames ) { + if (elem.nodeType == 1) + elem.className = classNames != undefined ? + jQuery.grep(elem.className.split(/\s+/), function(className){ + return !jQuery.className.has( classNames, className ); + }).join(" ") : + ""; + }, + + // internal only, use hasClass("class") + has: function( elem, className ) { + return jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1; + } + }, + + // A method for quickly swapping in/out CSS properties to get correct calculations + swap: function( elem, options, callback ) { + var old = {}; + // Remember the old values, and insert the new ones + for ( var name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + callback.call( elem ); + + // Revert the old values + for ( var name in options ) + elem.style[ name ] = old[ name ]; + }, + + css: function( elem, name, force ) { + if ( name == "width" || name == "height" ) { + var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ]; + + function getWH() { + val = name == "width" ? elem.offsetWidth : elem.offsetHeight; + var padding = 0, border = 0; + jQuery.each( which, function() { + padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0; + border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0; + }); + val -= Math.round(padding + border); + } + + if ( jQuery(elem).is(":visible") ) + getWH(); + else + jQuery.swap( elem, props, getWH ); + + return Math.max(0, val); + } + + return jQuery.curCSS( elem, name, force ); + }, + + curCSS: function( elem, name, force ) { + var ret, style = elem.style; + + // A helper method for determining if an element's values are broken + function color( elem ) { + if ( !jQuery.browser.safari ) + return false; + + // defaultView is cached + var ret = defaultView.getComputedStyle( elem, null ); + return !ret || ret.getPropertyValue("color") == ""; + } + + // We need to handle opacity special in IE + if ( name == "opacity" && jQuery.browser.msie ) { + ret = jQuery.attr( style, "opacity" ); + + return ret == "" ? + "1" : + ret; + } + // Opera sometimes will give the wrong display answer, this fixes it, see #2037 + if ( jQuery.browser.opera && name == "display" ) { + var save = style.outline; + style.outline = "0 solid black"; + style.outline = save; + } + + // Make sure we're using the right name for getting the float value + if ( name.match( /float/i ) ) + name = styleFloat; + + if ( !force && style && style[ name ] ) + ret = style[ name ]; + + else if ( defaultView.getComputedStyle ) { + + // Only "float" is needed here + if ( name.match( /float/i ) ) + name = "float"; + + name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase(); + + var computedStyle = defaultView.getComputedStyle( elem, null ); + + if ( computedStyle && !color( elem ) ) + ret = computedStyle.getPropertyValue( name ); + + // If the element isn't reporting its values properly in Safari + // then some display: none elements are involved + else { + var swap = [], stack = [], a = elem, i = 0; + + // Locate all of the parent display: none elements + for ( ; a && color(a); a = a.parentNode ) + stack.unshift(a); + + // Go through and make them visible, but in reverse + // (It would be better if we knew the exact display type that they had) + for ( ; i < stack.length; i++ ) + if ( color( stack[ i ] ) ) { + swap[ i ] = stack[ i ].style.display; + stack[ i ].style.display = "block"; + } + + // Since we flip the display style, we have to handle that + // one special, otherwise get the value + ret = name == "display" && swap[ stack.length - 1 ] != null ? + "none" : + ( computedStyle && computedStyle.getPropertyValue( name ) ) || ""; + + // Finally, revert the display styles back + for ( i = 0; i < swap.length; i++ ) + if ( swap[ i ] != null ) + stack[ i ].style.display = swap[ i ]; + } + + // We should always get a number back from opacity + if ( name == "opacity" && ret == "" ) + ret = "1"; + + } else if ( elem.currentStyle ) { + var camelCase = name.replace(/\-(\w)/g, function(all, letter){ + return letter.toUpperCase(); + }); + + ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ]; + + // From the awesome hack by Dean Edwards + // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + + // If we're not dealing with a regular pixel number + // but a number that has a weird ending, we need to convert it to pixels + if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) { + // Remember the original values + var left = style.left, rsLeft = elem.runtimeStyle.left; + + // Put in the new values to get a computed value out + elem.runtimeStyle.left = elem.currentStyle.left; + style.left = ret || 0; + ret = style.pixelLeft + "px"; + + // Revert the changed values + style.left = left; + elem.runtimeStyle.left = rsLeft; + } + } + + return ret; + }, + + clean: function( elems, context ) { + var ret = []; + context = context || document; + // !context.createElement fails in IE with an error but returns typeof 'object' + if (typeof context.createElement == 'undefined') + context = context.ownerDocument || context[0] && context[0].ownerDocument || document; + + jQuery.each(elems, function(i, elem){ + if ( !elem ) + return; + + if ( elem.constructor == Number ) + elem += ''; + + // Convert html string into DOM nodes + if ( typeof elem == "string" ) { + // Fix "XHTML"-style tags in all browsers + elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){ + return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ? + all : + front + ">"; + }); + + // Trim whitespace, otherwise indexOf won't work as expected + var tags = jQuery.trim( elem ).toLowerCase(), div = context.createElement("div"); + + var wrap = + // option or optgroup + !tags.indexOf("", "" ] || + + !tags.indexOf("", "" ] || + + tags.match(/^<(thead|tbody|tfoot|colg|cap)/) && + [ 1, "", "
" ] || + + !tags.indexOf("", "" ] || + + // matched above + (!tags.indexOf("", "" ] || + + !tags.indexOf("", "" ] || + + // IE can't serialize and + diff -r 60453502674e -r a619b3ef3095 org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/PreviewerException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/PreviewerException.java Tue Apr 13 16:04:08 2010 -0700 @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2010 Symbian Foundation and/or its subsidiary(-ies). + * All rights reserved. + * This component and the accompanying materials are made available + * under the terms of the License "Eclipse Public License v1.0" + * which accompanies this distribution, and is available + * at the URL "http://www.eclipse.org/legal/epl-v10.html". + * + * Initial Contributors: + * Symbian Foundation - initial contribution. + * Contributors: + * Description: + * Overview: + * Details: + * Platforms/Drives/Compatibility: + * Assumptions/Requirement/Pre-requisites: + * Failures and causes: + */ +package org.symbian.tools.wrttools.previewer; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +public class PreviewerException extends CoreException { + private static final long serialVersionUID = 5555595753039913542L; + + public PreviewerException(String message) { + this(message, null); + } + + public PreviewerException(String message, Exception exception) { + super(new Status(IStatus.ERROR, PreviewerPlugin.PLUGIN_ID, message, exception)); + } + + public PreviewerException(Exception e) { + this(null, e); + } + + public PreviewerException(CoreException e) { + super(e.getStatus()); + } +} diff -r 60453502674e -r a619b3ef3095 org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/http/HttpPreviewer.java --- a/org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/http/HttpPreviewer.java Fri Apr 09 17:07:39 2010 -0700 +++ b/org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/http/HttpPreviewer.java Tue Apr 13 16:04:08 2010 -0700 @@ -35,9 +35,8 @@ } } - public File getLocalFile(String name) { - return WorkspaceResourcesServlet.getPreviewerResource(name); - - } + public File getLocalFile(String name) { + return WorkspaceResourcesServlet.getPreviewerResource(name); + } } diff -r 60453502674e -r a619b3ef3095 org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/http/WorkspaceResourcesServlet.java --- a/org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/http/WorkspaceResourcesServlet.java Fri Apr 09 17:07:39 2010 -0700 +++ b/org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/http/WorkspaceResourcesServlet.java Tue Apr 13 16:04:08 2010 -0700 @@ -18,7 +18,6 @@ *******************************************************************************/ package org.symbian.tools.wrttools.previewer.http; -import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -32,10 +31,9 @@ import java.util.Map; import java.util.StringTokenizer; import java.util.TreeMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import javax.servlet.ServletException; +import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -48,22 +46,21 @@ import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.symbian.tools.wrttools.previewer.PreviewerException; import org.symbian.tools.wrttools.previewer.PreviewerPlugin; +import org.symbian.tools.wrttools.previewer.http.handlers.PreviewerStaticResourceProvider; +import org.symbian.tools.wrttools.previewer.http.handlers.ProjectIndexResourceProvider; +import org.symbian.tools.wrttools.previewer.http.handlers.Providers; import org.symbian.tools.wrttools.util.CoreUtil; -import org.symbian.tools.wrttools.util.ProjectUtils; public class WorkspaceResourcesServlet extends HttpServlet { - private static final String PREVIEW_START = "/preview/wrt_preview.html"; - private static final String PREVIEW_PATH = "preview"; - private static final Object COMMAND_PATH = "__sym_command"; - private static final String STARTING_PAGE = "preview-frame.html"; - private static final String INDEX_PAGE = "wrt_preview_main.html"; - private static final long serialVersionUID = -3217197074249607950L; + private static final Map EXTENSION_CONTENT_TYPE = new TreeMap(); - private static final Pattern HEAD_TAG_PATTERN = Pattern.compile("", Pattern.CASE_INSENSITIVE); - private static final String SCRIPT = ""; + private static final long serialVersionUID = -3217197074249607950L; - private static final Map EXTENSION_CONTENT_TYPE = new TreeMap(); static { EXTENSION_CONTENT_TYPE.put("htm", "text/html"); EXTENSION_CONTENT_TYPE.put("html", "text/html"); @@ -77,6 +74,47 @@ EXTENSION_CONTENT_TYPE.put("js", "application/x-javascript"); } + private static String encode(String path) { + try { + StringBuffer result = new StringBuffer(); + String[] segments = new Path(path).segments(); + for (int i = 0; i < segments.length; i++) { + String string = segments[i]; + result.append("/"); + // java.net.URLEncoder encodes " " as "+" while Chrome needs "%20" + StringTokenizer tokenizer = new StringTokenizer(string, " ", false); + while (tokenizer.hasMoreElements()) { + result.append(URLEncoder.encode(tokenizer.nextToken(), "UTF-8")); + if (tokenizer.hasMoreTokens()) { + result.append("%20"); + } + } + } + return result.toString(); + } catch (UnsupportedEncodingException e) { + // Something is horribly wrong - JRE doesn't have UTF8? + throw new RuntimeException(e); + } + } + + public static IFile getFileFromUrl(String name) { + IPath path = getProjectRelativePath(name); + if (path != null) { + return getProjectResource(path); + } else { + return null; + } + } + + public static String getHttpUrl(IResource file) { + String uri = getServerURIForResource(file != null ? file.getFullPath().toString() : "/"); + if (uri != null) { + return uri; + } else { + return file.getLocationURI().toString(); + } + } + public static String getMimeTypeByExtension(String extension) { if (extension != null) { return EXTENSION_CONTENT_TYPE.get(extension.toLowerCase()); @@ -85,242 +123,159 @@ } } - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException { - long time = 0; - if (PreviewerPlugin.TRACE_SERVLET) { - time = System.currentTimeMillis(); - } - IPath path = new Path(req.getPathInfo()); - InputStream contents = null; - try { - contents = getSpecialResource(path, req.getParameterMap()); - if (contents == null) { - IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(path); - if (file.isAccessible() && !ProjectUtils.isExcluded(file)) { - contents = file.getContents(); + public static File getPreviewerResource(String name) { + try { + IPath path = getProjectRelativePath(name); + if (path != null) { + if (path.segmentCount() == 2 && PreviewerStaticResourceProvider.STARTING_PAGE.equals(path.segment(1))) { + path = new Path(PreviewerStaticResourceProvider.PREVIEW_START); + } else if (path.segmentCount() > 2 + && PreviewerStaticResourceProvider.PREVIEW_PATH.equals(path.segment(1))) { + path = path.removeFirstSegments(1); + } else { + return null; + } + URL pluginResource = FileLocator.find(PreviewerPlugin.getDefault().getBundle(), path, null); + if (pluginResource != null) { + URL url = FileLocator.toFileURL(pluginResource); + if (url != null) { + return new File(url.getPath()); + } + } + } + } catch (IOException e) { + PreviewerPlugin.log(e); + } + return null; + } + + public static String getPreviewerStartingPage(String widget) { + return getServerURIForResource(new Path(widget).append(PreviewerStaticResourceProvider.STARTING_PAGE) + .makeAbsolute().toString()); + } + + private static IPath getProjectRelativePath(String uri) { + IPath path = null; + try { + String root = getHttpUrl(null); + if (uri != null && uri.startsWith(root)) { + String fileName = uri.substring(root.length()); + fileName = URLDecoder.decode(fileName, "UTF-8"); + path = new Path(fileName); + if (path.segmentCount() == 2 && ProjectIndexResourceProvider.INDEX.equals(path.lastSegment())) { + IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(path.segment(0)); + path = new Path(project.getName()).append(CoreUtil.getIndexFile(project)); } - } - String mimeType = getMimeTypeByExtension(path.getFileExtension()); + } + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } catch (CoreException e) { + PreviewerPlugin.log(e); + } + return path; + } + + private static IFile getProjectResource(IPath path) { + IFile file; + file = ResourcesPlugin.getWorkspace().getRoot().getFile(path); + if (!file.isAccessible()) { + return null; + } else { + return file; + } + } + + private static String getServerURIForResource(String resourcePath) { + Path p = new Path(resourcePath); + if (p.segmentCount() > 1) { + IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(p.segment(0)); + try { + if (p.removeFirstSegments(1).toString().equals(CoreUtil.getIndexFile(project))) { + return getServerURIForResource(new Path(p.segment(0)).append(ProjectIndexResourceProvider.INDEX) + .makeAbsolute().toString()); + } + } catch (Exception e1) { + PreviewerPlugin.log(e1); + } + } + String uri = null; + try { + String path = WebappManager.WORKSPACE_RESOURCES_CONTEXT + resourcePath; + URL url = new URL("http", WebappManager.getHost(), WebappManager.getPort(), encode(path)); + uri = url.toString(); + } catch (MalformedURLException e) { + uri = null; + } + return uri; + } + + private final Providers providers = new Providers(); + + private void copyData(InputStream contents, OutputStream ouput) throws IOException { + byte[] buf = new byte[4048]; + int i; + while ((i = contents.read(buf)) >= 0) { + ouput.write(buf, 0, i); + } + } + + @SuppressWarnings("unchecked") + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + long time = 0; + if (PreviewerPlugin.TRACE_SERVLET) { + time = System.currentTimeMillis(); + } + try { + InputStream stream = providers.get(req.getPathInfo(), req.getParameterMap()); + String mimeType = getMimeTypeByExtension(new Path(req.getPathInfo()).getFileExtension()); if (mimeType != null) { resp.setContentType(mimeType); } - if (contents != null) { - copyData(contents, resp.getOutputStream()); - } else { - resp.setStatus(HttpServletResponse.SC_NOT_FOUND); - } - } catch (CoreException e) { - PreviewerPlugin.log(e); - } finally { - if (contents != null) { - contents.close(); - } - } - if (PreviewerPlugin.TRACE_SERVLET) { - System.out.println(MessageFormat.format( - "Resource {0} was downloaded in {1}", req.getPathInfo(), - System.currentTimeMillis() - time)); - } - } + if (stream != null) { + copyData(stream, resp.getOutputStream()); + } else { + PreviewerPlugin.log(String.format("Resource %s was not found", req.getPathInfo()), null); + resp.setStatus(HttpServletResponse.SC_NOT_FOUND); + } + + } catch (PreviewerException e) { + PreviewerPlugin.log(e); + throw new ServletException(e); + } + if (PreviewerPlugin.TRACE_SERVLET) { + System.out.println(MessageFormat.format("Resource {0} was downloaded in {1}", req.getPathInfo(), System + .currentTimeMillis() + - time)); + } + } @SuppressWarnings("unchecked") - private InputStream getSpecialResource(IPath path, Map parameters) throws IOException, - CoreException { - IPath relativePath = path.removeFirstSegments(1); - if (relativePath.segmentCount() == 1) { - if (STARTING_PAGE.equals(relativePath.segment(0))) { - return getPluginResourceStream(new Path( - PREVIEW_START)); - } else if (INDEX_PAGE.equals(relativePath.segment(0))) { - return getProjectIndexPage(path.segment(0)); - } - } else if (PREVIEW_PATH.equals(relativePath.segment(0))) { - return getPluginResourceStream(relativePath.makeAbsolute()); - } else if (COMMAND_PATH.equals(relativePath.segment(0))) { - if (path.segmentCount() == 3) { - PreviewerPlugin.getDefault().getCommandHandlerManager().handle(path.segment(2), path.segment(0), - parameters); + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + ServletInputStream inputStream = req.getInputStream(); + byte[] buff = new byte[1024]; + StringBuilder builder = new StringBuilder(); + int l; + while ((l = inputStream.read(buff)) > 0) { + builder.append(new String(buff, 0, l, "UTF-8")); + } + inputStream.close(); + JSONObject object = null; + try { + Object parseResult = new JSONParser().parse(builder.toString()); + if (parseResult instanceof JSONObject) { + object = (JSONObject) parseResult; } - } - return null; - } - - private InputStream getProjectIndexPage(String projectName) - throws IOException, CoreException { - IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject( - projectName); - if (project.isAccessible()) { - String indexFileName = CoreUtil.getIndexFile(project); - if (indexFileName != null) { - String string = CoreUtil.readFile(project, CoreUtil.getFile( - project, indexFileName)); - if (string != null) { - Matcher matcher = HEAD_TAG_PATTERN.matcher(string); - if (matcher.find()) { - string = matcher.replaceFirst(matcher.group() + SCRIPT); - } - return new ByteArrayInputStream(string.getBytes("UTF-8")); - } - } - } - return null; - } - - private InputStream getPluginResourceStream(IPath path) throws IOException { - URL url = FileLocator.find(PreviewerPlugin.getDefault().getBundle(), - path, null); - if (url != null) { - return url.openStream(); - } else { - return null; - } - } - - private void copyData(InputStream contents, OutputStream ouput) - throws IOException { - byte[] buf = new byte[4048]; - int i; - while ((i = contents.read(buf)) >= 0) { - ouput.write(buf, 0, i); - } - } - - public static String getHttpUrl(IResource file) { - String uri = getServerURIForResource(file != null ? file.getFullPath() - .toString() : "/"); - if (uri != null) { - return uri; - } else { - return file.getLocationURI().toString(); - } - } - - private static String getServerURIForResource(String resourcePath) { - Path p = new Path(resourcePath); - if (p.segmentCount() > 1) { - IProject project = ResourcesPlugin.getWorkspace().getRoot() - .getProject(p.segment(0)); - try { - if (p.removeFirstSegments(1).toString().equals( - CoreUtil.getIndexFile(project))) { - return getServerURIForResource(new Path(p.segment(0)) - .append(INDEX_PAGE).makeAbsolute().toString()); - } - } catch (Exception e1) { - PreviewerPlugin.log(e1); - } - } - String uri = null; - try { - String path = WebappManager.WORKSPACE_RESOURCES_CONTEXT - + resourcePath; - URL url = new URL("http", WebappManager.getHost(), WebappManager - .getPort(), encode(path)); - uri = url.toString(); - } catch (MalformedURLException e) { - uri = null; - } - return uri; - } - - private static String encode(String path) { - try { - StringBuffer result = new StringBuffer(); - String[] segments = new Path(path).segments(); - for (int i = 0; i < segments.length; i++) { - String string = segments[i]; - result.append("/"); - // java.net.URLEncoder encodes " " as "+" while Chrome needs - // "%20" - StringTokenizer tokenizer = new StringTokenizer(string, " ", - false); - while (tokenizer.hasMoreElements()) { - result.append(URLEncoder.encode(tokenizer.nextToken(), - "UTF-8")); - if (tokenizer.hasMoreTokens()) { - result.append("%20"); - } - } - } - return result.toString(); - } catch (UnsupportedEncodingException e) { - // Something is horribly wrong - JRE doesn't have UTF8? - throw new RuntimeException(e); - } - } - - public static IFile getFileFromUrl(String name) { - IPath path = getProjectRelativePath(name); - if (path != null) { - return getProjectResource(path); - } else { - return null; - } - } - - private static IPath getProjectRelativePath(String uri) { - IPath path = null; - try { - String root = getHttpUrl(null); - if (uri != null && uri.startsWith(root)) { - String fileName = uri.substring(root.length()); - fileName = URLDecoder.decode(fileName, "UTF-8"); - path = new Path(fileName); - if (path.segmentCount() == 2 && INDEX_PAGE.equals(path.lastSegment())) { - IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(path.segment(0)); - path = new Path(project.getName()).append(CoreUtil.getIndexFile(project)); - } - } - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } catch (CoreException e) { - PreviewerPlugin.log(e); - } - return path; - } - - private static IFile getProjectResource(IPath path) { - IFile file; - file = ResourcesPlugin.getWorkspace().getRoot().getFile(path); - if (!file.isAccessible()) { - return null; - } else { - return file; - } - } - - public static String getPreviewerStartingPage(String widget) { - return getServerURIForResource(new Path(widget).append(STARTING_PAGE) - .makeAbsolute().toString()); - } - - public static File getPreviewerResource(String name) { - try { - IPath path = getProjectRelativePath(name); - if (path != null) { - if (path.segmentCount() == 2 - && STARTING_PAGE.equals(path.segment(1))) { - path = new Path(PREVIEW_START); - } else if (path.segmentCount() > 2 - && PREVIEW_PATH.equals(path.segment(1))) { - path = path.removeFirstSegments(1); - } else { - return null; - } - URL pluginResource = FileLocator.find(PreviewerPlugin - .getDefault().getBundle(), path, null); - if (pluginResource != null) { - URL url = FileLocator.toFileURL(pluginResource); - if (url != null) { - return new File(url.getPath()); - } - } - } - } catch (IOException e) { - PreviewerPlugin.log(e); - } - return null; - } + } catch (ParseException e) { + PreviewerPlugin.log(e); + throw new ServletException(e); + } + try { + providers.post(req.getPathInfo(), req.getParameterMap(), object); + } catch (PreviewerException e) { + throw new ServletException(e); + } + resp.setStatus(HttpServletResponse.SC_OK); + } } diff -r 60453502674e -r a619b3ef3095 org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/http/handlers/CommandResourceProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/http/handlers/CommandResourceProvider.java Tue Apr 13 16:04:08 2010 -0700 @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2010 Symbian Foundation and/or its subsidiary(-ies). + * All rights reserved. + * This component and the accompanying materials are made available + * under the terms of the License "Eclipse Public License v1.0" + * which accompanies this distribution, and is available + * at the URL "http://www.eclipse.org/legal/epl-v10.html". + * + * Initial Contributors: + * Symbian Foundation - initial contribution. + * Contributors: + * Description: + * Overview: + * Details: + * Platforms/Drives/Compatibility: + * Assumptions/Requirement/Pre-requisites: + * Failures and causes: + */ +package org.symbian.tools.wrttools.previewer.http.handlers; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.json.simple.JSONObject; +import org.symbian.tools.wrttools.previewer.PreviewerPlugin; + +public class CommandResourceProvider implements ResourceProvider { + + public String[] getPaths() { + return new String[] { "__sym_command" }; + } + + public InputStream getResourceStream(IProject project, IPath resource, Map parameters) + throws IOException, CoreException { + if (resource.segmentCount() == 2) { + PreviewerPlugin.getDefault().getCommandHandlerManager().handle(resource.segment(1), project.getName(), + parameters); + } + return null; + } + + public void post(IProject project, IPath resource, Map parameterMap, JSONObject object) + throws IOException, CoreException { + // Do nothing + } + +} diff -r 60453502674e -r a619b3ef3095 org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/http/handlers/PreferencesResourceProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/http/handlers/PreferencesResourceProvider.java Tue Apr 13 16:04:08 2010 -0700 @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2010 Symbian Foundation and/or its subsidiary(-ies). + * All rights reserved. + * This component and the accompanying materials are made available + * under the terms of the License "Eclipse Public License v1.0" + * which accompanies this distribution, and is available + * at the URL "http://www.eclipse.org/legal/epl-v10.html". + * + * Initial Contributors: + * Symbian Foundation - initial contribution. + * Contributors: + * Description: + * Overview: + * Details: + * Platforms/Drives/Compatibility: + * Assumptions/Requirement/Pre-requisites: + * Failures and causes: + */ +package org.symbian.tools.wrttools.previewer.http.handlers; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.util.Map; +import java.util.Properties; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.json.simple.JSONObject; +import org.symbian.tools.wrttools.previewer.PreviewerPlugin; +import org.symbian.tools.wrttools.previewer.preview.ProjectPreferencesManager; + +public class PreferencesResourceProvider implements ResourceProvider { + public String[] getPaths() { + return new String[] { "preview/preferences.js" }; + } + + public InputStream getResourceStream(IProject project, IPath resource, Map parameters) + throws IOException, CoreException { + Properties projectPreferences = ProjectPreferencesManager.getProjectProperties(project); + String js = getJS(projectPreferences); + try { + return new ByteArrayInputStream(js.getBytes("UTF-8")); + } catch (UnsupportedEncodingException e) { + PreviewerPlugin.log(e); + } + return null; + } + + @SuppressWarnings("unchecked") + private String getJS(Properties projectPreferences) { + StringBuilder builder = new StringBuilder("NOKIA.emulator.prefs = "); + JSONObject jsonObject = new JSONObject(); + jsonObject.putAll(projectPreferences); + builder.append(jsonObject.toJSONString()).append(";\n"); + return builder.toString(); + } + + public void post(IProject project, IPath resource, Map parameterMap, JSONObject object) + throws IOException, CoreException { + String key = (String) object.get("key"); + String value = (String) object.get("value"); + Properties projectPreferences = ProjectPreferencesManager.getProjectProperties(project); + String oldValue = (String) projectPreferences.get(key); + if (oldValue != value && (oldValue == null || !oldValue.equals(value))) { + projectPreferences.put(key, value); + ProjectPreferencesManager.setProjectProperties(project, projectPreferences); + } + } + +} diff -r 60453502674e -r a619b3ef3095 org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/http/handlers/PreviewerStaticResourceProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/http/handlers/PreviewerStaticResourceProvider.java Tue Apr 13 16:04:08 2010 -0700 @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2010 Symbian Foundation and/or its subsidiary(-ies). + * All rights reserved. + * This component and the accompanying materials are made available + * under the terms of the License "Eclipse Public License v1.0" + * which accompanies this distribution, and is available + * at the URL "http://www.eclipse.org/legal/epl-v10.html". + * + * Initial Contributors: + * Symbian Foundation - initial contribution. + * Contributors: + * Description: + * Overview: + * Details: + * Platforms/Drives/Compatibility: + * Assumptions/Requirement/Pre-requisites: + * Failures and causes: + */ +package org.symbian.tools.wrttools.previewer.http.handlers; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.Map; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.json.simple.JSONObject; +import org.symbian.tools.wrttools.previewer.PreviewerPlugin; + +public class PreviewerStaticResourceProvider implements ResourceProvider { + public static final String STARTING_PAGE = "preview-frame.html"; + public static final String PREVIEW_PATH = "preview"; + public static final String PREVIEW_START = "/preview/wrt_preview.html"; + + public String[] getPaths() { + return new String[] { STARTING_PAGE, PREVIEW_PATH }; + } + + public InputStream getResourceStream(IProject project, IPath resource, Map parameters) + throws IOException { + if (STARTING_PAGE.equals(resource.toString())) { + resource = new Path(PREVIEW_START); + } + URL url = FileLocator.find(PreviewerPlugin.getDefault().getBundle(), resource, null); + if (url != null) { + return url.openStream(); + } else { + return null; + } + } + + public void post(IProject project, IPath resource, Map parameterMap, JSONObject object) + throws IOException, CoreException { + // Do nothing + } + +} diff -r 60453502674e -r a619b3ef3095 org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/http/handlers/ProjectIndexResourceProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/http/handlers/ProjectIndexResourceProvider.java Tue Apr 13 16:04:08 2010 -0700 @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2010 Symbian Foundation and/or its subsidiary(-ies). + * All rights reserved. + * This component and the accompanying materials are made available + * under the terms of the License "Eclipse Public License v1.0" + * which accompanies this distribution, and is available + * at the URL "http://www.eclipse.org/legal/epl-v10.html". + * + * Initial Contributors: + * Symbian Foundation - initial contribution. + * Contributors: + * Description: + * Overview: + * Details: + * Platforms/Drives/Compatibility: + * Assumptions/Requirement/Pre-requisites: + * Failures and causes: + */ +package org.symbian.tools.wrttools.previewer.http.handlers; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.json.simple.JSONObject; +import org.symbian.tools.wrttools.util.CoreUtil; + +public class ProjectIndexResourceProvider implements ResourceProvider { + public static final String INDEX = "wrt_preview_main.html"; + private static final Pattern HEAD_TAG_PATTERN = Pattern.compile("", + Pattern.CASE_INSENSITIVE); + private static final String SCRIPT = ""; + + public String[] getPaths() { + return new String[] { INDEX }; + } + + public InputStream getResourceStream(IProject project, IPath resource, Map parameters) + throws IOException, CoreException { + return getProjectIndexPage(project.getName()); + } + + private InputStream getProjectIndexPage(String projectName) throws IOException, CoreException { + IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); + if (project.isAccessible()) { + String indexFileName = CoreUtil.getIndexFile(project); + if (indexFileName != null) { + String string = CoreUtil.readFile(project, CoreUtil.getFile(project, indexFileName)); + if (string != null) { + Matcher matcher = HEAD_TAG_PATTERN.matcher(string); + if (matcher.find()) { + string = matcher.replaceFirst(matcher.group() + SCRIPT); + } + return new ByteArrayInputStream(string.getBytes("UTF-8")); + } + } + } + return null; + } + + public void post(IProject project, IPath resource, Map parameterMap, JSONObject object) + throws IOException, CoreException { + // Do nothing + } + +} diff -r 60453502674e -r a619b3ef3095 org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/http/handlers/Providers.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/http/handlers/Providers.java Tue Apr 13 16:04:08 2010 -0700 @@ -0,0 +1,119 @@ +/** + * Copyright (c) 2010 Symbian Foundation and/or its subsidiary(-ies). + * All rights reserved. + * This component and the accompanying materials are made available + * under the terms of the License "Eclipse Public License v1.0" + * which accompanies this distribution, and is available + * at the URL "http://www.eclipse.org/legal/epl-v10.html". + * + * Initial Contributors: + * Symbian Foundation - initial contribution. + * Contributors: + * Description: + * Overview: + * Details: + * Platforms/Drives/Compatibility: + * Assumptions/Requirement/Pre-requisites: + * Failures and causes: + */ +package org.symbian.tools.wrttools.previewer.http.handlers; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; +import java.util.TreeMap; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.json.simple.JSONObject; +import org.symbian.tools.wrttools.previewer.PreviewerException; + +/** + * Path is usually in the form /preview/{project name}/{path} + * + * There are following spacial cases: + * - Static previewer resource from plugin is returned when {path} begins with + * "preview" or is "preview-frame.html" + * - Preferences resource is "preview/preferences.js" + * - Index page (main HTML page of the WRT application) is always wrt_preview_main.html + * - Debugger commands are submitted to URL __sym_command + * + * All other URLs return workspace resources. + */ +public class Providers { + private final Map HANDLERS = new TreeMap(); + private final ResourceProvider defaultHandler = new WorkspaceResourceProvider(); + public Providers() { + addPaths(new PreviewerStaticResourceProvider()); + addPaths(new PreferencesResourceProvider()); + addPaths(new ProjectIndexResourceProvider()); + addPaths(new CommandResourceProvider()); + } + + private void addPaths(ResourceProvider handler) { + for (String path : handler.getPaths()) { + HANDLERS.put(path, handler); + } + } + + public InputStream get(String url, Map parameters) throws PreviewerException { + final IProject project = getProject(url); + final IPath resource = new Path(url).removeFirstSegments(1); + final ResourceProvider provider = getHandlerForPath(resource); + try { + return provider.getResourceStream(project, resource, parameters); + } catch (IOException e) { + throw new PreviewerException(e); + } catch (CoreException e) { + throw new PreviewerException(e); + } + } + + private ResourceProvider getHandlerForPath(IPath resource) { + ResourceProvider provider = null; + IPath mapping = resource; + while (mapping.segmentCount() > 0) { + provider = HANDLERS.get(mapping.toString()); + if (provider != null) { + break; + } + mapping = mapping.removeLastSegments(1); + } + if (provider == null) { + provider = defaultHandler; + } + return provider; + } + + private IProject getProject(String url) throws PreviewerException { + final IPath path = new Path(url); + if (path.segmentCount() < 2) { + throw new PreviewerException(String.format("Invalid path: %s", url)); + } + IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(path.segment(0)); + if (!project.isAccessible()) { + throw new PreviewerException(String.format("Project %s does not exist or is not open", project.getName())); + } + return project; + } + + public ResourceProvider getHandlerForPostPath(String url) { + return null; + } + + public void post(String url, Map parameterMap, JSONObject object) throws PreviewerException { + final IProject project = getProject(url); + final IPath resource = new Path(url).removeFirstSegments(1); + final ResourceProvider provider = getHandlerForPath(resource); + try { + provider.post(project, resource, parameterMap, object); + } catch (IOException e) { + throw new PreviewerException(e); + } catch (CoreException e) { + throw new PreviewerException(e); + } + } +} diff -r 60453502674e -r a619b3ef3095 org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/http/handlers/ResourceProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/http/handlers/ResourceProvider.java Tue Apr 13 16:04:08 2010 -0700 @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2010 Symbian Foundation and/or its subsidiary(-ies). + * All rights reserved. + * This component and the accompanying materials are made available + * under the terms of the License "Eclipse Public License v1.0" + * which accompanies this distribution, and is available + * at the URL "http://www.eclipse.org/legal/epl-v10.html". + * + * Initial Contributors: + * Symbian Foundation - initial contribution. + * Contributors: + * Description: + * Overview: + * Details: + * Platforms/Drives/Compatibility: + * Assumptions/Requirement/Pre-requisites: + * Failures and causes: + */ +package org.symbian.tools.wrttools.previewer.http.handlers; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.json.simple.JSONObject; + +public interface ResourceProvider { + String[] getPaths(); + InputStream getResourceStream(IProject project, IPath resource, Map parameters) throws IOException, + CoreException; + void post(IProject project, IPath resource, Map parameterMap, JSONObject object) + throws IOException, CoreException; +} diff -r 60453502674e -r a619b3ef3095 org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/http/handlers/WorkspaceResourceProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/http/handlers/WorkspaceResourceProvider.java Tue Apr 13 16:04:08 2010 -0700 @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2010 Symbian Foundation and/or its subsidiary(-ies). + * All rights reserved. + * This component and the accompanying materials are made available + * under the terms of the License "Eclipse Public License v1.0" + * which accompanies this distribution, and is available + * at the URL "http://www.eclipse.org/legal/epl-v10.html". + * + * Initial Contributors: + * Symbian Foundation - initial contribution. + * Contributors: + * Description: + * Overview: + * Details: + * Platforms/Drives/Compatibility: + * Assumptions/Requirement/Pre-requisites: + * Failures and causes: + */ +package org.symbian.tools.wrttools.previewer.http.handlers; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.json.simple.JSONObject; + +public class WorkspaceResourceProvider implements ResourceProvider { + public String[] getPaths() { + return null; + } + + public InputStream getResourceStream(IProject project, IPath resource, Map parameters) + throws IOException, CoreException { + IFile file = project.getFile(resource); + if (file.isAccessible()) { + return file.getContents(); + } else { + return null; + } + } + + public void post(IProject project, IPath resource, Map parameterMap, JSONObject object) + throws IOException, CoreException { + // Do nothing + } + +} diff -r 60453502674e -r a619b3ef3095 org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/preview/MozillaPreviewPage.java --- a/org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/preview/MozillaPreviewPage.java Fri Apr 09 17:07:39 2010 -0700 +++ b/org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/preview/MozillaPreviewPage.java Tue Apr 13 16:04:08 2010 -0700 @@ -3,10 +3,14 @@ import java.io.File; import java.io.IOException; import java.net.URL; +import java.util.Iterator; +import java.util.Map; +import java.util.Properties; import org.eclipse.core.net.proxy.IProxyData; import org.eclipse.core.net.proxy.IProxyService; import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.Platform; import org.eclipse.jface.action.Action; @@ -54,6 +58,7 @@ } public void clearPreferences() { + boolean needsRefresh = false; nsIServiceManager servMgr = null; try { servMgr = Mozilla.getInstance().getServiceManager(); @@ -63,16 +68,10 @@ "@mozilla.org/cookiemanager;1", nsICookieManager.NS_ICOOKIEMANAGER_IID); nsISimpleEnumerator enumerator = cookieManager.getEnumerator(); - boolean needsRefresh = false; while (enumerator.hasMoreElements()) { nsICookie cookie = (nsICookie) enumerator.getNext().queryInterface(nsICookie.NS_ICOOKIE_IID); - if (isRelevantPreference(cookie.getName())) { - cookieManager.remove(cookie.getHost(), cookie.getName(), cookie.getPath(), false); - needsRefresh = true; - } - } - if (needsRefresh) { - refresh(true); + cookieManager.remove(cookie.getHost(), cookie.getName(), cookie.getPath(), false); + needsRefresh = true; } } } catch (Exception x) { @@ -81,15 +80,26 @@ // Mozilla. We don't want to pollute the error log with this return; } - } - - private boolean isRelevantPreference(String path) { - if (path != null && path.matches("Nokia_WRT#/preview/.*/preview-frame.html#.*")) { - String key = path.substring(path.lastIndexOf("#") + 1); - return !"_WRT_VERSION".equals(key) && !"NOKIA_EMULATOR_DEVICE_MODE".equals(key) - && !"NOKIA_EMULATOR_DEVICE".equals(key); + try { + Properties properties = ProjectPreferencesManager.getProjectProperties(project); + for (Iterator> i = properties.entrySet().iterator(); i.hasNext();) { + Map.Entry entry = i.next(); + if (entry.getKey() == null || !entry.getKey().toString().startsWith("__SYM_")) { + i.remove(); + needsRefresh = true; + } + } + if (needsRefresh) { + ProjectPreferencesManager.setProjectProperties(project, properties); + } + } catch (IOException e) { + PreviewerPlugin.log(e); + } catch (CoreException e) { + PreviewerPlugin.log(e); } - return false; + if (needsRefresh) { + refresh(true); + } } private synchronized void initMozilla() { diff -r 60453502674e -r a619b3ef3095 org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/preview/ProjectPreferencesManager.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/preview/ProjectPreferencesManager.java Tue Apr 13 16:04:08 2010 -0700 @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2010 Symbian Foundation and/or its subsidiary(-ies). + * All rights reserved. + * This component and the accompanying materials are made available + * under the terms of the License "Eclipse Public License v1.0" + * which accompanies this distribution, and is available + * at the URL "http://www.eclipse.org/legal/epl-v10.html". + * + * Initial Contributors: + * Symbian Foundation - initial contribution. + * Contributors: + * Description: + * Overview: + * Details: + * Platforms/Drives/Compatibility: + * Assumptions/Requirement/Pre-requisites: + * Failures and causes: + */ +package org.symbian.tools.wrttools.previewer.preview; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Path; +import org.symbian.tools.wrttools.previewer.PreviewerPlugin; + +public class ProjectPreferencesManager { + private static IFile getPreferencesXml(IProject project) { + return project.getFile(new Path(".settings").append(PreviewerPlugin.PLUGIN_ID).addFileExtension("xml")); + } + + public static synchronized Properties getProjectProperties(IProject project) throws IOException, CoreException { + Properties projectPreferences = new Properties(); + IFile xml = getPreferencesXml(project); + if (xml.isAccessible()) { + InputStream contents = null; + try { + contents = xml.getContents(); + projectPreferences.loadFromXML(contents); + } finally { + if (contents != null) { + contents.close(); + } + } + } + return projectPreferences; + } + + public static synchronized void setProjectProperties(IProject project, Properties properties) throws IOException, + CoreException { + IFile xml = getPreferencesXml(project); + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + properties.storeToXML(stream, null); + stream.close(); + ByteArrayInputStream inputStream = new ByteArrayInputStream(stream.toByteArray()); + if (xml.exists()) { + xml.setContents(inputStream, IFile.KEEP_HISTORY, new NullProgressMonitor()); + } else { + xml.create(inputStream, false, new NullProgressMonitor()); + } + inputStream.close(); + } +} diff -r 60453502674e -r a619b3ef3095 org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/preview/RefreshJob.java --- a/org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/preview/RefreshJob.java Fri Apr 09 17:07:39 2010 -0700 +++ b/org.symbian.tools.wrttools.previewer/src/org/symbian/tools/wrttools/previewer/preview/RefreshJob.java Tue Apr 13 16:04:08 2010 -0700 @@ -82,7 +82,8 @@ public static boolean isRelevantResource(IResource resource) { return resource.getType() == IResource.FILE && !resource.getFullPath().segment(1).equalsIgnoreCase("preview") - && !"wgz".equalsIgnoreCase(resource.getFileExtension()); + && !"wgz".equalsIgnoreCase(resource.getFileExtension()) + && !(PreviewerPlugin.PLUGIN_ID + ".xml").equals(resource.getName()); } private final IResourceDelta delta;