- Timestamp:
- 11/28/19 14:41:10 (5 years ago)
- Location:
- src
- Files:
-
- 8 added
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
src/main/java/geniusweb/partiesserver/RunParty.java
r1 r8 60 60 String name = request.getPathInfo().substring(1); 61 61 log.log(Level.INFO, "request to run " + name); 62 62 System.setSecurityManager(new SimpleSecurityManager()); 63 63 AvailableParty party = AvailablePartiesRepo.instance().get(name); 64 64 if (party == null) { -
src/main/java/geniusweb/partiesserver/repository/AvailablePartiesRepo.java
r1 r8 12 12 * Stores all currently available parties that can be run. 13 13 */ 14 public class AvailablePartiesRepo extends DefaultListenable<String> implements Repository<String, AvailableParty> { 14 public class AvailablePartiesRepo extends DefaultListenable<String> 15 implements Repository<String, AvailableParty> { 15 16 private static final AvailablePartiesRepo instance = new AvailablePartiesRepo(); 16 17 … … 37 38 public void put(AvailableParty entity) { 38 39 availableParties.put(entity.getID(), entity); 39 notify Change(entity.getID());40 notifyListeners(entity.getID()); 40 41 } 41 42 … … 43 44 public void remove(String id) { 44 45 availableParties.remove(id); 45 notify Change(id);46 notifyListeners(id); 46 47 } 47 48 -
src/main/java/geniusweb/partiesserver/repository/RunningPartiesRepo.java
r1 r8 74 74 runningParties.put(id, newParty); 75 75 } 76 notify Change(id);76 notifyListeners(id); 77 77 } 78 78 … … 87 87 runningParties.put(id, newParty); 88 88 } 89 notify Change(id);89 notifyListeners(id); 90 90 91 91 } … … 125 125 } 126 126 } 127 notify Change(id);127 notifyListeners(id); 128 128 } 129 129 -
src/main/java/geniusweb/partiesserver/repository/RunningParty.java
r4 r8 9 9 import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; 10 10 11 import geniusweb.actions.Action;12 11 import geniusweb.actions.PartyId; 13 12 import geniusweb.connection.DefaultConnection; 14 13 import geniusweb.partiesserver.RunningPartiesUpdater; 14 import geniusweb.partiesserver.websocket.PartySocket; 15 15 import geniusweb.party.Party; 16 16 import geniusweb.party.inform.Inform; … … 40 40 * set when someone contacts our socket. null if not set. 41 41 */ 42 private final transient DefaultConnection<Inform, Action>connection;42 private final transient PartySocket connection; 43 43 44 44 /** … … 58 58 */ 59 59 protected RunningParty(Party party, PartyId id, String name, Date start, 60 Date end, DefaultConnectionconn) {60 Date end, PartySocket conn) { 61 61 if (party == null || id == null || name == null || start == null 62 62 || end == null) { … … 101 101 * @param name The name, this should match the filename in the repo 102 102 * (without the .jar). 103 * @param maxRunTimeMS the maximum runtime for this party (ms). The {@link RunningPartiesUpdater} 104 * will keep an eye on the time and handle removal after time is up. 103 * @param maxRunTimeMS the maximum runtime for this party (ms). The 104 * {@link RunningPartiesUpdater} will keep an eye on the 105 * time and handle removal after time is up. 105 106 * 106 107 */ … … 212 213 */ 213 214 public void inform(Inform info) { 214 connection.notify Change(info);215 connection.notifyListeners(info); 215 216 } 216 217 … … 223 224 * @throws IllegalStateException if the party is already connected. 224 225 */ 225 public RunningParty withConnection( 226 DefaultConnection<Inform, Action> newconn) { 226 public RunningParty withConnection(PartySocket newconn) { 227 227 if (newconn == null) 228 228 throw new NullPointerException("newconn must be not null"); -
src/main/java/geniusweb/partiesserver/websocket/PartySocket.java
r4 r8 5 5 import java.net.URI; 6 6 import java.util.Date; 7 import java.util.List; 8 import java.util.concurrent.CopyOnWriteArrayList; 7 9 import java.util.logging.Level; 8 10 … … 23 25 import geniusweb.actions.Action; 24 26 import geniusweb.actions.PartyId; 25 import geniusweb.connection. DefaultConnection;27 import geniusweb.connection.ConnectionEnd; 26 28 import geniusweb.partiesserver.repository.RunningPartiesRepo; 27 29 import geniusweb.partiesserver.repository.RunningParty; 28 30 import geniusweb.party.Party; 29 import geniusweb.party.inform.Finished;30 31 import geniusweb.party.inform.Inform; 31 32 import geniusweb.party.inform.Settings; … … 41 42 */ 42 43 @ServerEndpoint("/party/{party}") 43 public class PartySocket extends DefaultConnection<Inform, Action> {44 public class PartySocket implements ConnectionEnd<Inform, Action> { 44 45 private final static ObjectMapper jackson = new ObjectMapper(); 45 46 private final Reporter log; 46 47 private final RunningPartiesRepo runningparties; 48 private final List<Listener<Inform>> listeners = new CopyOnWriteArrayList<Listener<Inform>>(); 47 49 48 50 // should all be final, except that we can only set them when start is … … 86 88 runningparties.removeListener(this); 87 89 session.close(new CloseReason(CloseCodes.GOING_AWAY, 88 " party died"));90 "detected that party vanished")); 89 91 } catch (IOException e) { 90 92 log.log(Level.WARNING, … … 131 133 party.inform(info); 132 134 } catch (Throwable e) { 133 // simple sandbox 134 log.log(Level.WARNING, "Party failed on inform:", e); 135 log.log(Level.WARNING, "Party failed on inform.", e); 136 // we don't use jackson.writeValueAsString(e) here because 137 // CloseReason has 123 char limit. 138 // The error will be too large to fit and will be truncated 139 // therefore we send a plain string and hope that enough 140 // will arrive at the other side (the protocol) 141 session.close(new CloseReason( 142 CloseReason.CloseCodes.CLOSED_ABNORMALLY, 143 "party threw exception: " + collectReasons(e))); 135 144 } 136 } // else dead but that's handled in the listener above 145 } // else party is dead but that's handled in the listener above 146 } 147 148 /** 149 * 150 * @param e an exception 151 * @return collect all reasons and sub-reasons 152 */ 153 private String collectReasons(Throwable e) { 154 String reason = ""; 155 do { 156 reason = reason + " : " + e.getClass().getSimpleName() + ":" 157 + e.getMessage(); 158 e = e.getCause(); 159 } while (e != null); 160 return reason; 137 161 } 138 162 … … 145 169 */ 146 170 private void sniff(Inform info, RunningParty party) throws IOException { 147 if (info instanceof Finished) { 148 session.close(new CloseReason(CloseCodes.GOING_AWAY, 149 "session reached agreement")); 150 } else if (info instanceof Settings) { 171 // do NOT sniff Finished messages and close sockets. Parties and their 172 // sockets need to stay running till all messages are handled 173 if (info instanceof Settings) { 151 174 Date end = ((Settings) info).getProgress().getTerminationTime(); 152 175 runningparties.replace(party.withEndTime(end)); … … 209 232 } 210 233 234 @Override 235 public void addListener(Listener<Inform> l) { 236 listeners.add(l); 237 } 238 239 @Override 240 public void removeListener(Listener<Inform> l) { 241 listeners.remove(l); 242 } 243 244 /** 245 * This should only be called by the owner of the listenable, not by 246 * listeners or others. Avoid calling this from synchronized blocks as a 247 * notified listener might immediately make more calls to you. 248 * <p> 249 * Any listeners that throw an exception will be intercepted and their 250 * stacktrace is printed. 251 * 252 * @param data information about the change. 253 */ 254 public void notifyListeners(Inform data) { 255 for (Listener<Inform> l : listeners) { 256 l.notifyChange(data); 257 } 258 } 259 211 260 } -
src/test/java/geniusweb/partiesserver/AvailablePartiesUpdaterTest.java
r1 r8 31 31 32 32 public class AvailablePartiesUpdaterTest { 33 private static final String RANDOMPARTY = "target/jars/randomparty-1.1.0.jar"; 33 34 private static final int TESTRATE = 200; // check file changes every 200ms 34 35 @SuppressWarnings("unchecked") … … 146 147 public void randomPartyJarTest() throws IOException, InterruptedException { 147 148 init(); 148 Files.copy(Paths.get("target/jars/randomparty-1.0.0.jar"), 149 tmpdir.resolve(RNDPARTY)); 149 Files.copy(Paths.get(RANDOMPARTY), tmpdir.resolve(RNDPARTY)); 150 150 151 151 Thread.sleep(2 * TESTRATE); … … 157 157 public void removeJarTest() throws IOException, InterruptedException { 158 158 init(); 159 Files.copy(Paths.get( "target/jars/randomparty-1.0.0.jar"), RNDPARTY);159 Files.copy(Paths.get(RANDOMPARTY), RNDPARTY); 160 160 Thread.sleep(2 * TESTRATE); 161 161 assertEquals(1, repo.list().size()); … … 169 169 public void removeRootTest() throws IOException, InterruptedException { 170 170 init(); 171 Files.copy(Paths.get( "target/jars/randomparty-1.0.0.jar"), RNDPARTY);171 Files.copy(Paths.get(RANDOMPARTY), RNDPARTY); 172 172 Thread.sleep(2 * TESTRATE); 173 173 assertEquals(1, repo.list().size()); -
src/test/java/geniusweb/partiesserver/JavaClientTest.java
r7 r8 39 39 */ 40 40 public class JavaClientTest { 41 // private static final String JSON = "{\"jobs\":[\"jobs1\"]}"; 41 private static final String RANDOMPARTY = "http://localhost:8080/partiesserver/run/randomparty-1.1.0"; 42 // private static final String JSON = "{\"jobs\":[\"jobs1\"]}"; 42 43 // private static final String JOBS1PROFILE = "{\"LinearAdditiveUtilitySpace\":{\"issueUtilities\":{\"lease car\":{\"discreteutils\":{\"valueUtilities\":{\"no\":0,\"yes\":1}}},\"permanent contract\":{\"discreteutils\":{\"valueUtilities\":{\"no\":0,\"yes\":1}}},\"career development opportunities\":{\"discreteutils\":{\"valueUtilities\":{\"high\":1,\"low\":0,\"medium\":0.5}}},\"fte\":{\"discreteutils\":{\"valueUtilities\":{\"1.0\":0.75,\"0.6\":0.25,\"0.8\":0.5}}},\"salary\":{\"discreteutils\":{\"valueUtilities\":{\"4000\":1.0,\"2500\":0.25,\"3500\":0.75,\"2000\":0,\"3000\":0.3}}},\"work from home\":{\"discreteutils\":{\"valueUtilities\":{\"1\":0.5,\"2\":0.666666666666,\"0\":0.333333333}}}},\"issueWeights\":{\"lease car\":0.06,\"permanent contract\":0.16,\"career development opportunities\":0.04,\"fte\":0.32,\"salary\":0.24,\"work from home\":0.18},\"domain\":{\"name\":\"jobs\",\"issuesValues\":{\"lease car\":{\"values\":[\"yes\",\"no\"]},\"permanent contract\":{\"values\":[\"yes\",\"no\"]},\"career development opportunities\":{\"values\":[\"low\",\"medium\",\"high\"]},\"fte\":{\"values\":[\"0.6\",\"0.8\",\"1.0\"]},\"salary\":{\"values\":[\"2000\",\"2500\",\"3000\",\"3500\",\"4000\"]},\"work from home\":{\"values\":[\"0\",\"1\",\"2\"]}}},\"name\":\"jobs1\"}}"; 43 44 private EmbeddedTomcat tomcat = new EmbeddedTomcat(); … … 60 61 public void after() throws Throwable { 61 62 Thread.sleep(2000); 63 System.setSecurityManager(null); 62 64 tomcat.stop(); 63 65 } … … 157 159 */ 158 160 private String startParty() throws IOException, InterruptedException { 159 URL url = new URL( 160 "http://localhost:8080/partiesserver/run/randomparty-1.0.0"); 161 URL url = new URL(RANDOMPARTY); 161 162 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 162 163 conn.setRequestMethod("GET"); -
src/test/java/geniusweb/partiesserver/repository/RunningPartyTest.java
r1 r8 16 16 import com.fasterxml.jackson.databind.ObjectMapper; 17 17 18 import geniusweb.actions.Action;19 18 import geniusweb.actions.PartyId; 20 import geniusweb.connection.DefaultConnection; 21 import geniusweb.partiesserver.repository.AvailableParty; 22 import geniusweb.partiesserver.repository.RunningParty; 19 import geniusweb.partiesserver.websocket.PartySocket; 23 20 import geniusweb.party.Capabilities; 24 21 import geniusweb.party.DefaultParty; … … 90 87 RunningParty rparty = new RunningParty(party1, id1, "name1", now, end, 91 88 null); 92 DefaultConnection<Inform, Action> connection = mock( 93 DefaultConnection.class); 89 PartySocket connection = mock(PartySocket.class); 94 90 rparty = rparty.withConnection(connection); 95 91 } … … 99 95 RunningParty rparty = new RunningParty(party1, id1, "name1", now, end, 100 96 null); 101 DefaultConnection<Inform, Action> connection = mock( 102 DefaultConnection.class); 97 PartySocket connection = mock(PartySocket.class); 103 98 rparty = rparty.withConnection(connection); 104 99 rparty = rparty.withConnection(connection); … … 112 107 RunningParty rparty = new RunningParty(party1, id1, "name1", now, end, 113 108 null); 114 DefaultConnection<Inform, Action> connection = mock( 115 DefaultConnection.class); 109 PartySocket connection = mock(PartySocket.class); 116 110 rparty = rparty.withConnection(connection); 117 111 … … 120 114 121 115 ArgumentCaptor<Inform> argument = ArgumentCaptor.forClass(Inform.class); 122 verify(connection, times(1)).notify Change(argument.capture());116 verify(connection, times(1)).notifyListeners(argument.capture()); 123 117 assertEquals(info, argument.getValue()); 124 118 } -
src/test/java/geniusweb/partiesserver/websocket/PartySocketTest.java
r1 r8 23 23 import geniusweb.actions.EndNegotiation; 24 24 import geniusweb.actions.PartyId; 25 import geniusweb.connection.Connection ;25 import geniusweb.connection.ConnectionEnd; 26 26 import geniusweb.partiesserver.repository.RunningPartiesRepo; 27 27 import geniusweb.partiesserver.repository.RunningParty; 28 import geniusweb.partiesserver.websocket.PartySocket;29 28 import geniusweb.party.Party; 30 29 import geniusweb.party.inform.Inform; … … 83 82 84 83 @SuppressWarnings("unchecked") 85 Connection <Inform, Action> connection = mock(Connection.class);84 ConnectionEnd<Inform, Action> connection = mock(ConnectionEnd.class); 86 85 /* 87 86 * we must call runningparty directly on this one because
Note:
See TracChangeset
for help on using the changeset viewer.