001/** 002 * GRANITE DATA SERVICES 003 * Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S. 004 * 005 * This file is part of the Granite Data Services Platform. 006 * 007 * *** 008 * 009 * Community License: GPL 3.0 010 * 011 * This file is free software: you can redistribute it and/or modify 012 * it under the terms of the GNU General Public License as published 013 * by the Free Software Foundation, either version 3 of the License, 014 * or (at your option) any later version. 015 * 016 * This file is distributed in the hope that it will be useful, but 017 * WITHOUT ANY WARRANTY; without even the implied warranty of 018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 019 * GNU General Public License for more details. 020 * 021 * You should have received a copy of the GNU General Public License 022 * along with this program. If not, see <http://www.gnu.org/licenses/>. 023 * 024 * *** 025 * 026 * Available Commercial License: GraniteDS SLA 1.0 027 * 028 * This is the appropriate option if you are creating proprietary 029 * applications and you are not prepared to distribute and share the 030 * source code of your application under the GPL v3 license. 031 * 032 * Please visit http://www.granitedataservices.com/license for more 033 * details. 034 */ 035package org.granite.client.tide.data.impl; 036 037import java.util.ArrayList; 038import java.util.Arrays; 039import java.util.HashMap; 040import java.util.List; 041import java.util.Map; 042 043import org.granite.client.messaging.RemoteService; 044import org.granite.client.messaging.ResultFaultIssuesResponseListener; 045import org.granite.client.messaging.events.FaultEvent; 046import org.granite.client.messaging.events.IssueEvent; 047import org.granite.client.messaging.events.ResultEvent; 048import org.granite.client.tide.Context; 049import org.granite.client.tide.data.EntityManager; 050import org.granite.client.tide.data.PersistenceManager; 051import org.granite.client.tide.data.RemoteInitializer; 052import org.granite.client.tide.impl.FaultHandler; 053import org.granite.client.tide.impl.ResultHandler; 054import org.granite.client.tide.server.ServerSession; 055import org.granite.logging.Logger; 056import org.granite.tide.invocation.InvocationCall; 057import org.granite.tide.invocation.InvocationResult; 058 059/** 060 * @author William DRAI 061 */ 062public class RemoteInitializerImpl implements RemoteInitializer { 063 064 private static final Logger log = Logger.getLogger(RemoteInitializerImpl.class); 065 066 private final Context context; 067 private boolean enabled = true; 068 069 070 public RemoteInitializerImpl(Context context) { 071 this.context = context; 072 } 073 074 @Override 075 public void setEnabled(boolean enabled) { 076 this.enabled = enabled; 077 } 078 079 @Override 080 public boolean isEnabled() { 081 return enabled; 082 } 083 084 private List<Object[]> objectsInitializing = new ArrayList<Object[]>(); 085 086 /** 087 * {@inheritDoc} 088 */ 089 public boolean initializeObject(ServerSession serverSession, Object entity, String propertyName, Object object) { 090 if (!enabled || context.isFinished()) 091 return false; 092 093 log.debug("initialize {0}", ObjectUtil.toString(object)); 094 095 EntityManager entityManager = PersistenceManager.getEntityManager(entity); 096 if (entityManager == null) 097 return false; 098 099 entityManager.addReference(entity, null, null); 100 101 synchronized (objectsInitializing) { 102 objectsInitializing.add(new Object[] { context, entity, propertyName }); 103 } 104 105 context.callLater(new DoInitializeObjects(serverSession)); 106 return true; 107 } 108 109 public class DoInitializeObjects implements Runnable { 110 111 private final ServerSession serverSession; 112 113 public DoInitializeObjects(ServerSession serverSession) { 114 this.serverSession = serverSession; 115 } 116 117 public void run() { 118 Map<Object, List<String>> initMap = new HashMap<Object, List<String>>(); 119 120 synchronized (objectsInitializing) { 121 for (int i = 0; i < objectsInitializing.size(); i++) { 122 if (objectsInitializing.get(i)[0] != context) 123 continue; 124 125 List<String> propertyNames = initMap.get(objectsInitializing.get(i)[1]); 126 if (propertyNames == null) { 127 propertyNames = Arrays.asList((String)objectsInitializing.get(i)[2]); 128 initMap.put(objectsInitializing.get(i)[1], propertyNames); 129 } 130 else 131 propertyNames.add((String)objectsInitializing.get(i)[2]); 132 133 objectsInitializing.remove(i--); 134 } 135 } 136 137 RemoteService rs = serverSession.getRemoteService(); 138 for (Object entity : initMap.keySet()) { 139 rs.newInvocation("initializeObject", entity, initMap.get(entity).toArray(), new InvocationCall()) 140 .addListener(new InitializerListener(serverSession, entity)).invoke(); 141 142 } 143 } 144 } 145 146 147 public class InitializerListener extends ResultFaultIssuesResponseListener { 148 149 private final ServerSession serverSession; 150 private final Object entity; 151 152 public InitializerListener(ServerSession serverSession, Object entity) { 153 this.serverSession = serverSession; 154 this.entity = entity; 155 } 156 157 @Override 158 public void onResult(final ResultEvent event) { 159 context.callLater(new Runnable() { 160 public void run() { 161 EntityManager entityManager = PersistenceManager.getEntityManager(entity); 162 163 boolean saveUninitializeAllowed = entityManager.isUninitializeAllowed(); 164 try { 165 entityManager.setUninitializeAllowed(false); 166 167 // Assumes objects is a PersistentCollection or PersistentMap 168 new ResultHandler<Object>(serverSession, null, null).handleResult(context, (InvocationResult) event.getResult(), ((InvocationResult) event.getResult()).getResult(), null); 169 } 170 finally { 171 entityManager.setUninitializeAllowed(saveUninitializeAllowed); 172 } 173 } 174 }); 175 } 176 177 @Override 178 public void onFault(final FaultEvent event) { 179 context.callLater(new Runnable() { 180 public void run() { 181 log.error("Fault initializing collection " + ObjectUtil.toString(entity) + " " + event.toString()); 182 183 new FaultHandler<Object>(serverSession, null, null).handleFault(context, event.getMessage()); 184 } 185 }); 186 } 187 188 @Override 189 public void onIssue(final IssueEvent event) { 190 context.callLater(new Runnable() { 191 public void run() { 192 log.error("Fault initializing collection " + ObjectUtil.toString(entity) + " " + event.toString()); 193 194 new FaultHandler<Object>(serverSession, null, null).handleFault(context, null); 195 } 196 }); 197 } 198 } 199}