diff --git a/api/src/com/cloud/api/response/FirewallRuleResponse.java b/api/src/com/cloud/api/response/FirewallRuleResponse.java index 1c98d3d5d90..96e02f12976 100644 --- a/api/src/com/cloud/api/response/FirewallRuleResponse.java +++ b/api/src/com/cloud/api/response/FirewallRuleResponse.java @@ -43,7 +43,7 @@ public class FirewallRuleResponse extends BaseResponse { @SerializedName("virtualmachinedisplayname") @Param(description="the VM display name for the port forwarding rule") private String virtualMachineDisplayName; - @SerializedName("publicipaddress") @Param(description="the public ip address for the port forwarding rule") + @SerializedName("ipaddress") @Param(description="the public ip address for the port forwarding rule") private String publicIpAddress; public Long getId() { diff --git a/api/src/com/cloud/api/response/IpForwardingRuleResponse.java b/api/src/com/cloud/api/response/IpForwardingRuleResponse.java index 648562b219a..45aaa6e0e4d 100644 --- a/api/src/com/cloud/api/response/IpForwardingRuleResponse.java +++ b/api/src/com/cloud/api/response/IpForwardingRuleResponse.java @@ -43,7 +43,7 @@ public class IpForwardingRuleResponse extends BaseResponse { @SerializedName("virtualmachinedisplayname") @Param(description="the VM display name for the port forwarding rule") private String virtualMachineDisplayName; - @SerializedName("publicipaddress") @Param(description="the public ip address for the port forwarding rule") + @SerializedName("ipaddress") @Param(description="the public ip address for the port forwarding rule") private String publicIpAddress; public Long getId() { diff --git a/client/tomcatconf/components.xml.in b/client/tomcatconf/components.xml.in index 1eca3242fec..71461e0e30f 100755 --- a/client/tomcatconf/components.xml.in +++ b/client/tomcatconf/components.xml.in @@ -64,6 +64,7 @@ + diff --git a/cloud.spec b/cloud.spec index d46620697a9..8a2afd21e86 100644 --- a/cloud.spec +++ b/cloud.spec @@ -487,6 +487,7 @@ fi %{_javadir}/%{name}-xenserver-5.6.0-1.jar %{_javadir}/%{name}-xmlrpc-common-3.*.jar %{_javadir}/%{name}-xmlrpc-client-3.*.jar +%{_javadir}/%{name}-jstl-1.2.jar %files core %defattr(0644,root,root,0755) diff --git a/core/.classpath b/core/.classpath index 17a6103c14d..1867836084a 100644 --- a/core/.classpath +++ b/core/.classpath @@ -11,7 +11,6 @@ - @@ -39,5 +38,6 @@ + diff --git a/debian/cloud-deps.install b/debian/cloud-deps.install index be8604a5cdc..a169016f278 100644 --- a/debian/cloud-deps.install +++ b/debian/cloud-deps.install @@ -15,3 +15,4 @@ /usr/share/java/cloud-xenserver-5.6.0-1.jar /usr/share/java/cloud-xmlrpc-common-3.*.jar /usr/share/java/cloud-xmlrpc-client-3.*.jar +/usr/share/java/cloud-jstl-*.jar diff --git a/patches/systemvm/debian/config/root/firewall.sh b/patches/systemvm/debian/config/root/firewall.sh index 2def133e108..494361057a2 100755 --- a/patches/systemvm/debian/config/root/firewall.sh +++ b/patches/systemvm/debian/config/root/firewall.sh @@ -91,8 +91,6 @@ add_one_to_one_nat_entry() { if [ "$op" == "-A" ] then iptables -P FORWARD DROP - else - iptables -P FORWARD ACCEPT fi iptables $op FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT iptables $op FORWARD -i eth2 -o eth0 -d $guestIp -m state --state NEW -j ACCEPT diff --git a/server/.classpath b/server/.classpath index 8a0c5b39e0c..fe6302cf152 100644 --- a/server/.classpath +++ b/server/.classpath @@ -13,13 +13,13 @@ - - + + diff --git a/server/src/com/cloud/api/ApiGsonHelper.java b/server/src/com/cloud/api/ApiGsonHelper.java index 9877d27bdba..4e11d4b1977 100644 --- a/server/src/com/cloud/api/ApiGsonHelper.java +++ b/server/src/com/cloud/api/ApiGsonHelper.java @@ -14,3 +14,4 @@ public class ApiGsonHelper { return s_gBuilder; } } + diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index 7613b6db72a..0120fbf02c5 100755 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -274,9 +274,9 @@ public class ApiServer implements HttpRequestHandler { response.setStatusCode(se.getErrorCode()); response.setReasonPhrase(se.getDescription()); BasicHttpEntity body = new BasicHttpEntity(); - body.setContentType("text/xml; charset=UTF-8"); + body.setContentType("text/xml"); String responseStr = ""+se.getErrorCode()+" : "+se.getDescription()+""; - body.setContent(new ByteArrayInputStream(responseStr.getBytes())); + body.setContent(new ByteArrayInputStream(responseStr.getBytes("UTF-8"))); response.setEntity(body); sb.append(" " + se.getErrorCode() + " " + responseStr.length()); @@ -714,19 +714,19 @@ public class ApiServer implements HttpRequestHandler { BasicHttpEntity body = new BasicHttpEntity(); if (BaseCmd.RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) { // JSON response - body.setContentType("text/javascript; charset=UTF-8"); + body.setContentType("text/javascript"); if (responseText == null) { - body.setContent(new ByteArrayInputStream("{ \"error\" : { \"description\" : \"Internal Server Error\" } }".getBytes())); + body.setContent(new ByteArrayInputStream("{ \"error\" : { \"description\" : \"Internal Server Error\" } }".getBytes("UTF-8"))); } } else { - body.setContentType("text/xml; charset=UTF-8"); + body.setContentType("text/xml"); if (responseText == null) { - body.setContent(new ByteArrayInputStream("Internal Server Error".getBytes())); + body.setContent(new ByteArrayInputStream("Internal Server Error".getBytes("UTF-8"))); } } if (responseText != null) { - body.setContent(new ByteArrayInputStream(responseText.getBytes())); + body.setContent(new ByteArrayInputStream(responseText.getBytes("UTF-8"))); } resp.setEntity(body); } catch (Exception ex) { diff --git a/server/src/com/cloud/api/ApiServlet.java b/server/src/com/cloud/api/ApiServlet.java index 1e6e87eba11..0ba8243be90 100755 --- a/server/src/com/cloud/api/ApiServlet.java +++ b/server/src/com/cloud/api/ApiServlet.java @@ -320,14 +320,10 @@ public class ApiServlet extends HttpServlet { } else { resp.setContentType("text/xml"); } - resp.setStatus(isError? HttpServletResponse.SC_INTERNAL_SERVER_ERROR : HttpServletResponse.SC_OK); - byte[] respBytes = response.getBytes(); - resp.setContentLength(respBytes.length); - OutputStream os = resp.getOutputStream(); - os.write(respBytes); - os.flush(); - os.close(); - resp.flushBuffer(); + resp.setStatus(isError? HttpServletResponse.SC_INTERNAL_SERVER_ERROR : HttpServletResponse.SC_OK); + + // use getWriter() instead of manually manipulate encoding to have better localization support + resp.getWriter().print(response); } catch (IOException ioex) { if (s_logger.isTraceEnabled()) { s_logger.trace("exception writing response: " + ioex); diff --git a/server/src/com/cloud/api/response/ApiResponseSerializer.java b/server/src/com/cloud/api/response/ApiResponseSerializer.java index ca1852eaaf6..85e60baa3d6 100644 --- a/server/src/com/cloud/api/response/ApiResponseSerializer.java +++ b/server/src/com/cloud/api/response/ApiResponseSerializer.java @@ -4,10 +4,10 @@ import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.util.ArrayList; import java.util.Date; -import java.util.LinkedList; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.apache.log4j.Logger; @@ -28,6 +28,16 @@ public class ApiResponseSerializer { return toXMLSerializedString(result); } } + + private static final Pattern s_unicodeEscapePattern = Pattern.compile("\\\\u([0-9A-Fa-f]{4})"); + public static String unescape(String escaped) { + String str = escaped; + Matcher matcher = s_unicodeEscapePattern.matcher(str); + while(matcher.find()) { + str = str.replaceAll("\\" + matcher.group(0), Character.toString((char)Integer.parseInt(matcher.group(1), 16))); + } + return str; + } private static String toJSONSerializedString(ResponseObject result) { if (result != null) { @@ -39,10 +49,12 @@ public class ApiResponseSerializer { List responses = ((ListResponse)result).getResponses(); if ((responses != null) && !responses.isEmpty()) { int count = responses.size(); - String jsonStr = gson.toJson(responses.get(0)); + String jsonStr = gson.toJson(responses.get(0));; + jsonStr = unescape(jsonStr); sb.append("{ \"" + responses.get(0).getObjectName() + "\" : [ " + jsonStr); for (int i = 1; i < count; i++) { jsonStr = gson.toJson(responses.get(i)); + jsonStr = unescape(jsonStr); sb.append(", " + jsonStr); } sb.append(" ] }"); @@ -54,6 +66,7 @@ public class ApiResponseSerializer { } else { String jsonStr = gson.toJson(result); if ((jsonStr != null) && !"".equals(jsonStr)) { + jsonStr = unescape(jsonStr); if (result instanceof AsyncJobResponse || result instanceof CreateCmdResponse) { sb.append(jsonStr); } else { diff --git a/server/src/com/cloud/hypervisor/KVMGuru.java b/server/src/com/cloud/hypervisor/KVMGuru.java index 32527dc5b88..ccbe4e0a27e 100644 --- a/server/src/com/cloud/hypervisor/KVMGuru.java +++ b/server/src/com/cloud/hypervisor/KVMGuru.java @@ -13,6 +13,7 @@ import com.cloud.vm.VirtualMachineProfile; @Local(value=HypervisorGuru.class) public class KVMGuru extends HypervisorGuruBase implements HypervisorGuru { @Inject GuestOSDao _guestOsDao; + @Override public HypervisorType getHypervisorType() { return HypervisorType.KVM; @@ -33,5 +34,4 @@ public class KVMGuru extends HypervisorGuruBase implements HypervisorGuru { return to; } - } diff --git a/server/src/com/cloud/hypervisor/VMwareGuru.java b/server/src/com/cloud/hypervisor/VMwareGuru.java new file mode 100644 index 00000000000..fb7f90d189a --- /dev/null +++ b/server/src/com/cloud/hypervisor/VMwareGuru.java @@ -0,0 +1,54 @@ +/** + * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +package com.cloud.hypervisor; + +import javax.ejb.Local; + +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.storage.GuestOSVO; +import com.cloud.storage.dao.GuestOSDao; +import com.cloud.template.VirtualMachineTemplate.BootloaderType; +import com.cloud.utils.component.Inject; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachineProfile; + +@Local(value=HypervisorGuru.class) +public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru { + @Inject GuestOSDao _guestOsDao; + + protected VMwareGuru() { + super(); + } + + @Override + public HypervisorType getHypervisorType() { + return HypervisorType.VmWare; + } + + @Override + public VirtualMachineTO implement(VirtualMachineProfile vm) { + VirtualMachineTO to = toVirtualMachineTO(vm); + to.setBootloader(BootloaderType.HVM); + + // Determine the VM's OS description + GuestOSVO guestOS = _guestOsDao.findById(vm.getVirtualMachine().getGuestOSId()); + to.setOs(guestOS.getDisplayName()); + return to; + } +} diff --git a/server/src/com/cloud/servlet/ConsoleProxyServlet.java b/server/src/com/cloud/servlet/ConsoleProxyServlet.java index b43bae7fdb7..7876a343a2b 100644 --- a/server/src/com/cloud/servlet/ConsoleProxyServlet.java +++ b/server/src/com/cloud/servlet/ConsoleProxyServlet.java @@ -66,15 +66,16 @@ public class ConsoleProxyServlet extends HttpServlet { } @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) { + protected void doGet(HttpServletRequest req, HttpServletResponse resp) { + try { String userId = null; String account = null; Account accountObj = null; - + Map params = new HashMap(); params.putAll(req.getParameterMap()); - + HttpSession session = req.getSession(false); if(session == null) { if(verifyRequest(params)) { diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 38c5b7ae4e6..c76667263b5 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -2245,9 +2245,15 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, VirtualM { if((publicIp.getAccountId().longValue() == vm.getAccountId())) { - _networkMgr.deletePortForwardingRule(rule.getId(),true);//delete the rule with the sys user's credentials - if(s_logger.isDebugEnabled()) - s_logger.debug("Rule "+rule.getId()+" for vm:"+vm.getHostName()+" is deleted successfully during expunge operation"); + if(publicIp.isOneToOneNat()){ + _networkMgr.deleteIpForwardingRule(rule.getId()); + if(s_logger.isDebugEnabled()) + s_logger.debug("Rule "+rule.getId()+" for vm:"+vm.getHostName()+" is deleted successfully during expunge operation"); + }else{ + _networkMgr.deletePortForwardingRule(rule.getId(),true);//delete the rule with the sys user's credentials + if(s_logger.isDebugEnabled()) + s_logger.debug("Rule "+rule.getId()+" for vm:"+vm.getHostName()+" is deleted successfully during expunge operation"); + } } } } diff --git a/ui/scripts/cloud.core.js b/ui/scripts/cloud.core.js index fff1902cc93..aa0637821d1 100644 --- a/ui/scripts/cloud.core.js +++ b/ui/scripts/cloud.core.js @@ -537,11 +537,11 @@ function createURL(url) { } function fromdb(val) { - return sanitizeXSS(unescape(noNull(val))); + return sanitizeXSS(noNull(val)); } function todb(val) { - return encodeURIComponent(escape(val)); + return encodeURIComponent(val); } var midmenuItemCount = 20; diff --git a/utils/src/com/cloud/utils/db/GenericDaoBase.java b/utils/src/com/cloud/utils/db/GenericDaoBase.java index dfa6d72c78a..a5dab05daa9 100755 --- a/utils/src/com/cloud/utils/db/GenericDaoBase.java +++ b/utils/src/com/cloud/utils/db/GenericDaoBase.java @@ -18,6 +18,7 @@ package com.cloud.utils.db; import java.io.Serializable; +import java.io.UnsupportedEncodingException; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; @@ -448,7 +449,20 @@ public abstract class GenericDaoBase implements Gene try { final Class type = field.getType(); if (type == String.class) { - field.set(entity, rs.getString(index)); + byte[] bytes = rs.getBytes(index); + if(bytes != null) { + try { + field.set(entity, new String(bytes, "UTF-8")); + } catch (IllegalArgumentException e) { + assert(false); + throw new CloudRuntimeException("IllegalArgumentException when converting UTF-8 data"); + } catch (UnsupportedEncodingException e) { + assert(false); + throw new CloudRuntimeException("UnsupportedEncodingException when converting UTF-8 data"); + } + } else { + field.set(entity, null); + } } else if (type == long.class) { field.setLong(entity, rs.getLong(index)); } else if (type == Long.class) { @@ -560,7 +574,16 @@ public abstract class GenericDaoBase implements Gene @DB(txn=false) @SuppressWarnings("unchecked") protected M getObject(Class type, ResultSet rs, int index) throws SQLException { if (type == String.class) { - return (M)rs.getString(index); + byte[] bytes = rs.getBytes(index); + if(bytes != null) { + try { + return (M)new String(bytes, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new CloudRuntimeException("UnsupportedEncodingException exception while converting UTF-8 data"); + } + } else { + return (M)null; + } } else if (type == int.class) { return (M)new Integer(rs.getInt(index)); } else if (type == Integer.class) { @@ -1197,10 +1220,23 @@ public abstract class GenericDaoBase implements Gene final Column column = attr.field.getAnnotation(Column.class); final int length = column != null ? column.length() : 255; + // to support generic localization, utilize MySql UTF-8 support if (length < str.length()) { - pstmt.setString(j, str.substring(0, column.length())); + try { + pstmt.setBytes(j, str.substring(0, column.length()).getBytes("UTF-8")); + } catch (UnsupportedEncodingException e) { + // no-way it can't support UTF-8 encoding + assert(false); + throw new CloudRuntimeException("UnsupportedEncodingException when saving string as UTF-8 data"); + } } else { - pstmt.setString(j, str); + try { + pstmt.setBytes(j, str.getBytes("UTF-8")); + } catch (UnsupportedEncodingException e) { + // no-way it can't support UTF-8 encoding + assert(false); + throw new CloudRuntimeException("UnsupportedEncodingException when saving string as UTF-8 data"); + } } } else if (attr.field.getType() == Date.class) { final Date date = (Date)value;