├── jpost ├── .gitignore ├── src │ └── main │ │ └── java │ │ └── com │ │ └── mindorks │ │ └── jpost │ │ ├── core │ │ ├── ChannelType.java │ │ ├── ChannelState.java │ │ ├── OnMessage.java │ │ ├── CustomChannel.java │ │ ├── PrivateChannel.java │ │ ├── Post.java │ │ ├── AbstractChannel.java │ │ ├── Channel.java │ │ ├── ChannelPost.java │ │ ├── PublicChannel.java │ │ ├── DefaultChannel.java │ │ ├── BroadcastCenter.java │ │ ├── Broadcast.java │ │ └── AbstractBroadcastCenter.java │ │ └── exceptions │ │ ├── NullObjectException.java │ │ ├── PermissionException.java │ │ ├── AlreadyExistsException.java │ │ ├── NoSuchChannelException.java │ │ ├── JPostNotRunningException.java │ │ ├── InvalidSubscriberException.java │ │ └── IllegalChannelStateException.java └── build.gradle ├── android-jpost ├── .gitignore ├── src │ └── main │ │ └── java │ │ └── com │ │ └── mindorks │ │ └── androidjpost │ │ ├── droid │ │ ├── OnUiThread.java │ │ ├── AndroidPublicChannel.java │ │ ├── AndroidDefaultChannel.java │ │ └── AndroidPrivateChannel.java │ │ ├── JPost.java │ │ └── AndroidBroadcastCenter.java └── build.gradle ├── java-jpost ├── .gitignore ├── build.gradle └── src │ └── main │ └── java │ └── com │ └── mindorks │ └── javajpost │ └── JPost.java ├── .gitignore ├── settings.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .travis.yml ├── src └── main │ └── java │ └── tes │ └── mindorks │ └── jpost │ ├── ChannelIds.java │ ├── message │ ├── Message1.java │ └── Message2.java │ ├── Application.java │ ├── subscriber │ ├── SubscriberAsync.java │ └── Subscriber.java │ ├── TestDefaultChannel.java │ ├── TestPublicChannel.java │ └── TestPrivateChannel.java ├── gradlew.bat ├── gradlew ├── LICENSE └── README.md /jpost/.gitignore: -------------------------------------------------------------------------------- 1 | build -------------------------------------------------------------------------------- /android-jpost/.gitignore: -------------------------------------------------------------------------------- 1 | build -------------------------------------------------------------------------------- /java-jpost/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | .gradle 3 | .idea 4 | local.properties -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'JPost' 2 | include ':jpost', ':android-jpost', ':java-jpost' 3 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/janishar/JPost/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | 3 | script: 4 | gradle check 5 | 6 | jdk: 7 | - oraclejdk8 8 | - oraclejdk7 9 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Sep 21 22:37:27 IST 2016 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.13-all.zip 7 | -------------------------------------------------------------------------------- /src/main/java/tes/mindorks/jpost/ChannelIds.java: -------------------------------------------------------------------------------- 1 | package tes.mindorks.jpost; 2 | 3 | /** 4 | * Created by janisharali on 24/09/16. 5 | */ 6 | public class ChannelIds { 7 | 8 | public static final int publicChannel1 = 1; 9 | public static final int privateChannel1 = 2; 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/tes/mindorks/jpost/message/Message1.java: -------------------------------------------------------------------------------- 1 | package tes.mindorks.jpost.message; 2 | 3 | /** 4 | * Created by janisharali on 24/09/16. 5 | */ 6 | public class Message1 { 7 | 8 | private String msg; 9 | 10 | public Message1(String msg) { 11 | this.msg = msg; 12 | } 13 | 14 | public String getMsg() { 15 | return "Message1: " + msg; 16 | } 17 | 18 | public void setMsg(String msg) { 19 | this.msg = msg; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/tes/mindorks/jpost/message/Message2.java: -------------------------------------------------------------------------------- 1 | package tes.mindorks.jpost.message; 2 | 3 | /** 4 | * Created by janisharali on 24/09/16. 5 | */ 6 | public class Message2 { 7 | 8 | private String msg; 9 | 10 | public Message2(String msg) { 11 | this.msg = msg; 12 | } 13 | 14 | public String getMsg() { 15 | return "Message2: " + msg; 16 | } 17 | 18 | public void setMsg(String msg) { 19 | this.msg = msg; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /jpost/src/main/java/com/mindorks/jpost/core/ChannelType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | package com.mindorks.jpost.core; 18 | 19 | /** 20 | * Created by janisharali on 22/09/16. 21 | */ 22 | public enum ChannelType { 23 | DEFAULT, PUBLIC, PRIVATE; 24 | } 25 | -------------------------------------------------------------------------------- /jpost/src/main/java/com/mindorks/jpost/core/ChannelState.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | package com.mindorks.jpost.core; 18 | 19 | /** 20 | * Created by janisharali on 22/09/16. 21 | */ 22 | public enum ChannelState { 23 | OPEN, STOPPED, TERMINATED; 24 | } 25 | -------------------------------------------------------------------------------- /jpost/src/main/java/com/mindorks/jpost/exceptions/NullObjectException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | package com.mindorks.jpost.exceptions; 18 | 19 | /** 20 | * Created by janisharali on 22/09/16. 21 | */ 22 | public class NullObjectException extends Exception{ 23 | 24 | public NullObjectException(String message) { 25 | super(message); 26 | } 27 | 28 | public String toString() { 29 | return "NullObjectException[" + super.getMessage() + "]"; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /jpost/src/main/java/com/mindorks/jpost/exceptions/PermissionException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | package com.mindorks.jpost.exceptions; 18 | 19 | /** 20 | * Created by janisharali on 22/09/16. 21 | */ 22 | public class PermissionException extends Exception{ 23 | 24 | public PermissionException(String message) { 25 | super(message); 26 | } 27 | 28 | public String toString() { 29 | return "PermissionException[" + super.getMessage() + "]"; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /jpost/src/main/java/com/mindorks/jpost/exceptions/AlreadyExistsException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | package com.mindorks.jpost.exceptions; 18 | 19 | /** 20 | * Created by janisharali on 22/09/16. 21 | */ 22 | public class AlreadyExistsException extends Exception{ 23 | 24 | public AlreadyExistsException(String message) { 25 | super(message); 26 | } 27 | 28 | public String toString() { 29 | return "AlreadyExistsException[" + super.getMessage() + "]"; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /jpost/src/main/java/com/mindorks/jpost/exceptions/NoSuchChannelException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | package com.mindorks.jpost.exceptions; 18 | 19 | /** 20 | * Created by janisharali on 22/09/16. 21 | */ 22 | public class NoSuchChannelException extends Exception{ 23 | 24 | public NoSuchChannelException(String message) { 25 | super(message); 26 | } 27 | 28 | public String toString() { 29 | return "NoSuchChannelException[" + super.getMessage() + "]"; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /android-jpost/src/main/java/com/mindorks/androidjpost/droid/OnUiThread.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | package com.mindorks.androidjpost.droid; 18 | 19 | import java.lang.annotation.ElementType; 20 | import java.lang.annotation.Retention; 21 | import java.lang.annotation.RetentionPolicy; 22 | import java.lang.annotation.Target; 23 | 24 | /** 25 | * Created by janisharali on 26/09/16. 26 | */ 27 | @Retention(RetentionPolicy.RUNTIME) 28 | @Target(ElementType.METHOD) 29 | public @interface OnUiThread { 30 | } 31 | -------------------------------------------------------------------------------- /jpost/src/main/java/com/mindorks/jpost/exceptions/JPostNotRunningException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | package com.mindorks.jpost.exceptions; 18 | 19 | /** 20 | * Created by janisharali on 22/09/16. 21 | */ 22 | public class JPostNotRunningException extends Exception{ 23 | 24 | public JPostNotRunningException(String message) { 25 | super(message); 26 | } 27 | 28 | public String toString() { 29 | return "JPostNotRunningException[" + super.getMessage() + "]"; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /jpost/src/main/java/com/mindorks/jpost/exceptions/InvalidSubscriberException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | package com.mindorks.jpost.exceptions; 18 | 19 | /** 20 | * Created by janisharali on 22/09/16. 21 | */ 22 | public class InvalidSubscriberException extends Exception{ 23 | 24 | public InvalidSubscriberException(String message) { 25 | super(message); 26 | } 27 | 28 | public String toString() { 29 | return "InvalidSubscriberException[" + super.getMessage() + "]"; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /jpost/src/main/java/com/mindorks/jpost/exceptions/IllegalChannelStateException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | package com.mindorks.jpost.exceptions; 18 | 19 | /** 20 | * Created by janisharali on 22/09/16. 21 | */ 22 | public class IllegalChannelStateException extends Exception{ 23 | 24 | public IllegalChannelStateException(String message) { 25 | super(message); 26 | } 27 | 28 | public String toString() { 29 | return "IllegalChannelStateException[" + super.getMessage() + "]"; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /jpost/src/main/java/com/mindorks/jpost/core/OnMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | package com.mindorks.jpost.core; 18 | 19 | import com.mindorks.jpost.core.Channel; 20 | 21 | import java.lang.annotation.ElementType; 22 | import java.lang.annotation.Retention; 23 | import java.lang.annotation.RetentionPolicy; 24 | import java.lang.annotation.Target; 25 | 26 | /** 27 | * Created by janisharali on 23/09/16. 28 | */ 29 | @Retention(RetentionPolicy.RUNTIME) 30 | @Target(ElementType.METHOD) 31 | public @interface OnMessage { 32 | int channelId() default Channel.DEFAULT_CHANNEL_ID; 33 | boolean isCommonReceiver() default false; 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/tes/mindorks/jpost/Application.java: -------------------------------------------------------------------------------- 1 | package tes.mindorks.jpost; 2 | 3 | import com.mindorks.javajpost.JPost; 4 | 5 | /** 6 | * Created by janisharali on 30/09/16. 7 | */ 8 | 9 | public class Application { 10 | 11 | public static void main(String[] args){ 12 | System.out.println(".......................DEFAULT CHANNEL TEST START.............................."); 13 | TestDefaultChannel.test(); 14 | try { 15 | Thread.sleep(3000); 16 | System.out.println(".......................DEFAULT CHANNEL TEST END.............................."); 17 | JPost.shutdown(); 18 | }catch (InterruptedException e){ 19 | e.printStackTrace(); 20 | } 21 | 22 | System.out.println(".......................PUBLIC CHANNEL TEST START.............................."); 23 | TestPublicChannel.test(); 24 | try { 25 | Thread.sleep(3000); 26 | System.out.println(".......................PUBLIC CHANNEL TEST END.............................."); 27 | JPost.shutdown(); 28 | }catch (InterruptedException e){ 29 | e.printStackTrace(); 30 | } 31 | 32 | System.out.println(".......................PRIVATE CHANNEL TEST START.............................."); 33 | TestPrivateChannel.test(); 34 | try { 35 | Thread.sleep(3000); 36 | System.out.println(".......................PRIVATE CHANNEL TEST END.............................."); 37 | JPost.shutdown(); 38 | }catch (InterruptedException e){ 39 | e.printStackTrace(); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /jpost/src/main/java/com/mindorks/jpost/core/CustomChannel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | package com.mindorks.jpost.core; 18 | 19 | import com.mindorks.jpost.exceptions.IllegalChannelStateException; 20 | import com.mindorks.jpost.exceptions.NullObjectException; 21 | 22 | import java.lang.ref.WeakReference; 23 | import java.util.concurrent.ConcurrentHashMap; 24 | import java.util.concurrent.PriorityBlockingQueue; 25 | 26 | /** 27 | * Created by janisharali on 22/09/16. 28 | */ 29 | public interface CustomChannel>, 30 | M extends ConcurrentHashMap>> 31 | extends Channel{ 32 | 33 | 34 | void terminateChannel(); 35 | 36 | void startChannel(); 37 | 38 | void stopChannel(); 39 | 40 | /** 41 | * 42 | * @param msg 43 | * @param subscriberIds 44 | * @param 45 | * @throws NullObjectException 46 | * @throws IllegalChannelStateException 47 | */ 48 | void broadcast(T msg, Integer... subscriberIds) throws NullObjectException, IllegalChannelStateException; 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/tes/mindorks/jpost/subscriber/SubscriberAsync.java: -------------------------------------------------------------------------------- 1 | package tes.mindorks.jpost.subscriber; 2 | 3 | 4 | import com.mindorks.javajpost.JPost; 5 | import com.mindorks.jpost.core.OnMessage; 6 | 7 | import tes.mindorks.jpost.ChannelIds; 8 | import tes.mindorks.jpost.message.Message1; 9 | import tes.mindorks.jpost.message.Message2; 10 | 11 | /** 12 | * Created by janisharali on 24/09/16. 13 | */ 14 | public class SubscriberAsync { 15 | 16 | private char classifier; 17 | public SubscriberAsync(char classifier) { 18 | this.classifier = classifier; 19 | JPost.getBroadcastCenter().addSubscriberAsync(this); 20 | } 21 | 22 | public SubscriberAsync(char classifier, int channelId) { 23 | this.classifier = classifier; 24 | JPost.getBroadcastCenter().addSubscriberAsync(channelId, this); 25 | } 26 | 27 | public SubscriberAsync(char classifier, int channelId, int subscriberId) { 28 | this.classifier = classifier; 29 | JPost.getBroadcastCenter().addSubscriberAsync(channelId, this, subscriberId); 30 | } 31 | 32 | public SubscriberAsync(T owner, char classifier, int channelId, int subscriberId) { 33 | this.classifier = classifier; 34 | try { 35 | JPost.getBroadcastCenter().addSubscriberAsync(owner, channelId, this, subscriberId); 36 | }catch (Exception e){ 37 | e.printStackTrace(); 38 | } 39 | } 40 | 41 | public void subscribeAsync(){ 42 | JPost.getBroadcastCenter().addSubscriberAsync(this); 43 | } 44 | 45 | 46 | @OnMessage 47 | private void onMessage1(Message1 msg){ 48 | System.out.println("SubscriberAsync" + classifier + ": "+ msg.getMsg()); 49 | } 50 | 51 | @OnMessage(channelId = ChannelIds.publicChannel1) 52 | private void onMessage1Pub(Message1 msg){ 53 | System.out.println("Subscriber" + classifier + ": "+ msg.getMsg()); 54 | } 55 | 56 | @OnMessage(channelId = ChannelIds.privateChannel1) 57 | private void onMessage1Pri(Message1 msg){ 58 | System.out.println("Subscriber" + classifier + ": "+ msg.getMsg()); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /jpost/src/main/java/com/mindorks/jpost/core/PrivateChannel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | package com.mindorks.jpost.core; 18 | 19 | import com.mindorks.jpost.exceptions.InvalidSubscriberException; 20 | import com.mindorks.jpost.exceptions.NullObjectException; 21 | 22 | import java.lang.ref.WeakReference; 23 | import java.util.concurrent.ConcurrentHashMap; 24 | import java.util.concurrent.PriorityBlockingQueue; 25 | 26 | /** 27 | * Created by janisharali on 22/09/16. 28 | */ 29 | public class PrivateChannel< 30 | Q extends PriorityBlockingQueue>, 31 | M extends ConcurrentHashMap>> 32 | extends PublicChannel{ 33 | 34 | private WeakReference channelOwnerRef; 35 | 36 | public PrivateChannel(Integer channelId, ChannelState state, ChannelType type, Q postQueue, M subscriberMap, WeakReference channelOwnerRef) { 37 | super(channelId, state, type, postQueue, subscriberMap); 38 | this.channelOwnerRef = channelOwnerRef; 39 | } 40 | 41 | protected WeakReference getChannelOwnerRef() { 42 | return channelOwnerRef; 43 | } 44 | 45 | protected synchronized void removeSubscriber(Integer subscriberId) throws NullObjectException,InvalidSubscriberException { 46 | if(subscriberId == null){ 47 | throw new NullObjectException("subscriberId is null"); 48 | } 49 | if(getSubscriberMap().containsKey(subscriberId)){ 50 | getSubscriberMap().remove(subscriberId); 51 | }else{ 52 | throw new InvalidSubscriberException("Subscriber with subscriberId " + subscriberId + " do not exists"); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /jpost/src/main/java/com/mindorks/jpost/core/Post.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | package com.mindorks.jpost.core; 18 | 19 | import com.mindorks.jpost.exceptions.NullObjectException; 20 | 21 | 22 | /** 23 | * Created by janisharali on 22/09/16. 24 | */ 25 | public interface Post { 26 | 27 | int PRIORITY_LOW = 1; 28 | int PRIORITY_MEDIUM = 2; 29 | int PRIORITY_HIGH = 3; 30 | 31 | /** 32 | * 33 | * @param message 34 | */ 35 | void setMessage(T message); 36 | 37 | /** 38 | * 39 | * @return 40 | */ 41 | T getMessage(); 42 | 43 | /** 44 | * 45 | * @param priority 46 | */ 47 | void setPriority(Integer priority); 48 | 49 | /** 50 | * 51 | * @return 52 | */ 53 | Integer getPriority(); 54 | 55 | /** 56 | * 57 | * @return 58 | * @throws NullObjectException 59 | */ 60 | K getSender() throws NullObjectException; 61 | 62 | /** 63 | * 64 | * @param sender 65 | */ 66 | void setSender(K sender); 67 | 68 | /** 69 | * 70 | * @param receivers 71 | */ 72 | void setReceivers(Object... receivers); 73 | 74 | /** 75 | * 76 | * @return 77 | */ 78 | Object[] getReceiversList(); 79 | 80 | /** 81 | * 82 | * @param isSerialised 83 | */ 84 | void setIsSerialised(boolean isSerialised); 85 | 86 | /** 87 | * 88 | * @return 89 | */ 90 | boolean isSerialised(); 91 | 92 | /** 93 | * 94 | * @param className 95 | */ 96 | void setSerialisedClassName(String className); 97 | 98 | /** 99 | * 100 | * @return 101 | */ 102 | String getSerialisedClassName(); 103 | } 104 | -------------------------------------------------------------------------------- /jpost/src/main/java/com/mindorks/jpost/core/AbstractChannel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | package com.mindorks.jpost.core; 18 | 19 | import java.lang.ref.WeakReference; 20 | import java.util.Collection; 21 | import java.util.concurrent.ConcurrentHashMap; 22 | import java.util.concurrent.PriorityBlockingQueue; 23 | 24 | /** 25 | * Created by janisharali on 22/09/16. 26 | */ 27 | public abstract class AbstractChannel>, 28 | M extends ConcurrentHashMap>> implements Channel{ 29 | 30 | private Integer channelId; 31 | private ChannelType channelType; 32 | private ChannelState channelState; 33 | private Q postQueue; 34 | private M subscriberMap; 35 | 36 | public AbstractChannel(Integer channelId, ChannelState state, ChannelType type, Q postQueue, M subscriberMap) { 37 | this.channelId = channelId; 38 | this.channelState = state; 39 | this.channelType = type; 40 | this.postQueue = postQueue; 41 | this.subscriberMap = subscriberMap; 42 | } 43 | 44 | @Override 45 | public Integer getChannelId() { 46 | return channelId; 47 | } 48 | 49 | @Override 50 | public ChannelType getChannelType() { 51 | return channelType; 52 | } 53 | 54 | @Override 55 | public ChannelState getChannelState() { 56 | return channelState; 57 | } 58 | 59 | @Override 60 | public void setChannelState(ChannelState state) { 61 | channelState = state; 62 | } 63 | 64 | @Override 65 | public Q getPostQueue() { 66 | return postQueue; 67 | } 68 | 69 | @Override 70 | public M getSubscriberMap() { 71 | return subscriberMap; 72 | } 73 | 74 | @Override 75 | public Collection> getAllSubscribersReferenceList() { 76 | return subscriberMap.values(); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /src/main/java/tes/mindorks/jpost/subscriber/Subscriber.java: -------------------------------------------------------------------------------- 1 | package tes.mindorks.jpost.subscriber; 2 | 3 | 4 | import com.mindorks.javajpost.JPost; 5 | import com.mindorks.jpost.core.OnMessage; 6 | 7 | import tes.mindorks.jpost.ChannelIds; 8 | import tes.mindorks.jpost.message.Message1; 9 | import tes.mindorks.jpost.message.Message2; 10 | 11 | /** 12 | * Created by janisharali on 24/09/16. 13 | */ 14 | public class Subscriber { 15 | private char classifier; 16 | public Subscriber(char classifier) { 17 | this.classifier = classifier; 18 | try { 19 | JPost.getBroadcastCenter().addSubscriber(this); 20 | }catch (Exception e){ 21 | e.printStackTrace(); 22 | } 23 | } 24 | 25 | public Subscriber(char classifier, int channelId) { 26 | this.classifier = classifier; 27 | try { 28 | JPost.getBroadcastCenter().addSubscriber(channelId, this); 29 | }catch (Exception e){ 30 | e.printStackTrace(); 31 | } 32 | } 33 | 34 | public Subscriber(char classifier, int channelId, int subscriberId) { 35 | this.classifier = classifier; 36 | try { 37 | JPost.getBroadcastCenter().addSubscriber(channelId, this, subscriberId); 38 | }catch (Exception e){ 39 | e.printStackTrace(); 40 | } 41 | } 42 | 43 | public Subscriber(T owner, char classifier, int channelId) { 44 | this.classifier = classifier; 45 | try { 46 | JPost.getBroadcastCenter().addSubscriber(owner, channelId, this); 47 | }catch (Exception e){ 48 | e.printStackTrace(); 49 | } 50 | } 51 | 52 | public Subscriber(T owner, char classifier, int channelId, int subscriberId) { 53 | this.classifier = classifier; 54 | try { 55 | JPost.getBroadcastCenter().addSubscriber(owner, channelId, this, subscriberId); 56 | }catch (Exception e){ 57 | e.printStackTrace(); 58 | } 59 | } 60 | 61 | @OnMessage 62 | private void onMessage1(Message1 msg){ 63 | System.out.println("Subscriber" + classifier + ": "+ msg.getMsg()); 64 | } 65 | 66 | @OnMessage(channelId = ChannelIds.publicChannel1) 67 | private void onMessage1Pub(Message1 msg){ 68 | System.out.println("Subscriber" + classifier + ": "+ msg.getMsg()); 69 | } 70 | 71 | @OnMessage(channelId = ChannelIds.privateChannel1) 72 | private void onMessage1Pri(Message1 msg){ 73 | System.out.println("Subscriber" + classifier + ": "+ msg.getMsg()); 74 | } 75 | 76 | @OnMessage(isCommonReceiver = true) 77 | private void onMessage2(Message2 msg){ 78 | System.out.println("Subscriber" + classifier + ": "+ msg.getMsg()); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /jpost/src/main/java/com/mindorks/jpost/core/Channel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | package com.mindorks.jpost.core; 18 | 19 | import com.mindorks.jpost.exceptions.*; 20 | import com.mindorks.jpost.exceptions.IllegalChannelStateException; 21 | 22 | import java.lang.ref.WeakReference; 23 | import java.lang.reflect.Method; 24 | import java.util.Collection; 25 | import java.util.concurrent.ConcurrentHashMap; 26 | import java.util.concurrent.PriorityBlockingQueue; 27 | 28 | /** 29 | * Created by janisharali on 22/09/16. 30 | */ 31 | public interface Channel>, 32 | M extends ConcurrentHashMap>> { 33 | 34 | int MSG_QUEUE_INITIAL_CAPACITY = 10; 35 | int SUBSCRIBER_INITIAL_CAPACITY = 10; 36 | int DEFAULT_CHANNEL_ID = -99999999; 37 | 38 | /** 39 | * 40 | * @return 41 | */ 42 | Integer getChannelId(); 43 | 44 | /** 45 | * 46 | * @return 47 | */ 48 | ChannelType getChannelType(); 49 | 50 | /** 51 | * 52 | * @return 53 | */ 54 | Q getPostQueue(); 55 | 56 | /** 57 | * 58 | * @return 59 | */ 60 | M getSubscriberMap(); 61 | 62 | /** 63 | * 64 | * @return 65 | */ 66 | ChannelState getChannelState(); 67 | 68 | /** 69 | * 70 | * @param state 71 | */ 72 | void setChannelState(ChannelState state); 73 | 74 | /** 75 | * 76 | * @param msg 77 | * @param 78 | * @throws NullObjectException 79 | * @throws IllegalChannelStateException 80 | */ 81 | void broadcast(T msg) throws NullObjectException, IllegalChannelStateException; 82 | 83 | /** 84 | * 85 | * @param subscriber 86 | * @param subscriberId 87 | * @param 88 | * @return 89 | * @throws NullObjectException 90 | * @throws AlreadyExistsException 91 | * @throws IllegalChannelStateException 92 | */ 93 | T addSubscriber(T subscriber, Integer subscriberId) throws NullObjectException, AlreadyExistsException, IllegalChannelStateException; 94 | 95 | /** 96 | * 97 | * @param subscriber 98 | * @param 99 | * @throws NullObjectException 100 | * @throws InvalidSubscriberException 101 | */ 102 | void removeSubscriber(T subscriber) throws NullObjectException, InvalidSubscriberException; 103 | 104 | >boolean deliverMessage(T subscriber, OnMessage msgAnnotation, Method method, P post); 105 | 106 | /** 107 | * 108 | * @return 109 | */ 110 | Collection> getAllSubscribersReferenceList(); 111 | } 112 | -------------------------------------------------------------------------------- /jpost/src/main/java/com/mindorks/jpost/core/ChannelPost.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | package com.mindorks.jpost.core; 18 | 19 | import com.mindorks.jpost.exceptions.NullObjectException; 20 | 21 | import java.util.List; 22 | 23 | /** 24 | * Created by janisharali on 23/09/16. 25 | */ 26 | public class ChannelPost implements Post { 27 | 28 | private T message; 29 | private V sender; 30 | private Integer channelId; 31 | private Integer priority; 32 | private Object[] receivers; 33 | private boolean isSerialised; 34 | private String className; 35 | 36 | public ChannelPost(T message, Integer channelId, Integer priority) { 37 | this.message = message; 38 | this.channelId = channelId; 39 | this.priority = priority; 40 | } 41 | 42 | public ChannelPost(T message, Integer channelId, Integer priority, boolean isSerialised, String className) { 43 | this.message = message; 44 | this.channelId = channelId; 45 | this.priority = priority; 46 | this.isSerialised = isSerialised; 47 | this.className = className; 48 | } 49 | 50 | @Override 51 | public void setMessage(T message){ 52 | this.message = message; 53 | } 54 | 55 | @Override 56 | public T getMessage() { 57 | return message; 58 | } 59 | 60 | @Override 61 | public void setPriority(Integer priority){ 62 | this.priority = priority; 63 | } 64 | 65 | @Override 66 | public Integer getPriority() { 67 | return priority; 68 | } 69 | 70 | @Override 71 | public V getSender() throws NullObjectException { 72 | return sender; 73 | } 74 | 75 | @Override 76 | public void setSender(V sender) { 77 | this.sender = sender; 78 | } 79 | 80 | @Override 81 | public void setReceivers(Object... receivers){ 82 | this.receivers = receivers; 83 | } 84 | 85 | @Override 86 | public Object[] getReceiversList() { 87 | return receivers; 88 | } 89 | 90 | @Override 91 | public void setIsSerialised(boolean isSerialised) { 92 | this.isSerialised = isSerialised; 93 | } 94 | 95 | @Override 96 | public boolean isSerialised() { 97 | return isSerialised; 98 | } 99 | 100 | @Override 101 | public void setSerialisedClassName(String className){ 102 | this.className = className; 103 | } 104 | 105 | @Override 106 | public String getSerialisedClassName() { 107 | return className; 108 | } 109 | 110 | public Integer getChannelId() { 111 | return channelId; 112 | } 113 | 114 | public void setChannelId(Integer channelId){ 115 | this.channelId = channelId; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /android-jpost/src/main/java/com/mindorks/androidjpost/droid/AndroidPublicChannel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | package com.mindorks.androidjpost.droid; 18 | 19 | import android.os.Handler; 20 | import android.os.Looper; 21 | 22 | import com.mindorks.jpost.core.PublicChannel; 23 | import com.mindorks.jpost.core.OnMessage; 24 | import com.mindorks.jpost.core.*; 25 | 26 | import java.lang.annotation.Annotation; 27 | import java.lang.ref.WeakReference; 28 | import java.lang.reflect.InvocationTargetException; 29 | import java.lang.reflect.Method; 30 | import java.util.concurrent.ConcurrentHashMap; 31 | import java.util.concurrent.PriorityBlockingQueue; 32 | 33 | /** 34 | * Created by janisharali on 22/09/16. 35 | */ 36 | public class AndroidPublicChannel>, 37 | M extends ConcurrentHashMap>> 38 | extends PublicChannel implements CustomChannel{ 39 | 40 | public AndroidPublicChannel(Integer channelId, ChannelState state, ChannelType type, Q postQueue, M subscriberMap) { 41 | super(channelId, state, type, postQueue, subscriberMap); 42 | } 43 | 44 | @Override 45 | public > boolean deliverMessage(T subscriber, OnMessage msgAnnotation, Method method, P post) { 46 | int channelId = msgAnnotation.channelId(); 47 | boolean isCommonReceiver = msgAnnotation.isCommonReceiver(); 48 | if (isCommonReceiver || getChannelId().equals(channelId)) { 49 | try { 50 | boolean methodFound = false; 51 | for (final Class paramClass : method.getParameterTypes()) { 52 | if (paramClass.equals(post.getMessage().getClass())) { 53 | methodFound = true; 54 | break; 55 | } 56 | } 57 | if (methodFound) { 58 | Annotation annotation = method.getAnnotation(OnUiThread.class); 59 | if (annotation != null) { 60 | runOnUiThread(subscriber, method, post); 61 | }else{ 62 | method.setAccessible(true); 63 | method.invoke(subscriber, post.getMessage()); 64 | } 65 | } 66 | return true; 67 | } catch (IllegalAccessException | InvocationTargetException e) { 68 | e.printStackTrace(); 69 | } 70 | } 71 | return false; 72 | } 73 | 74 | private void runOnUiThread(final T subscriber,final Method method,final Post post){ 75 | new Handler(Looper.getMainLooper()).post(new Runnable() { 76 | @Override 77 | public void run() { 78 | try { 79 | method.setAccessible(true); 80 | method.invoke(subscriber, post.getMessage()); 81 | } catch (IllegalAccessException | InvocationTargetException e) { 82 | e.printStackTrace(); 83 | } 84 | } 85 | }); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /android-jpost/src/main/java/com/mindorks/androidjpost/droid/AndroidDefaultChannel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | package com.mindorks.androidjpost.droid; 18 | 19 | 20 | import android.os.Handler; 21 | import android.os.Looper; 22 | 23 | import com.mindorks.jpost.core.OnMessage; 24 | import com.mindorks.jpost.core.ChannelPost; 25 | import com.mindorks.jpost.core.ChannelState; 26 | import com.mindorks.jpost.core.ChannelType; 27 | import com.mindorks.jpost.core.DefaultChannel; 28 | import com.mindorks.jpost.core.Post; 29 | 30 | import java.lang.annotation.Annotation; 31 | import java.lang.ref.WeakReference; 32 | import java.lang.reflect.InvocationTargetException; 33 | import java.lang.reflect.Method; 34 | import java.util.concurrent.ConcurrentHashMap; 35 | import java.util.concurrent.PriorityBlockingQueue; 36 | 37 | /** 38 | * Created by janisharali on 27/09/16. 39 | */ 40 | public class AndroidDefaultChannel< 41 | Q extends PriorityBlockingQueue>, 42 | M extends ConcurrentHashMap>> 43 | extends DefaultChannel { 44 | 45 | public AndroidDefaultChannel(Integer channelId, ChannelState state, ChannelType type, Q postQueue, M subscriberMap) { 46 | super(channelId, state, type, postQueue, subscriberMap); 47 | } 48 | 49 | @Override 50 | public > boolean deliverMessage(T subscriber, OnMessage msgAnnotation, Method method, P post) { 51 | int channelId = msgAnnotation.channelId(); 52 | boolean isCommonReceiver = msgAnnotation.isCommonReceiver(); 53 | if (isCommonReceiver || getChannelId().equals(channelId)) { 54 | try { 55 | boolean methodFound = false; 56 | for (final Class paramClass : method.getParameterTypes()) { 57 | if (paramClass.equals(post.getMessage().getClass())) { 58 | methodFound = true; 59 | break; 60 | } 61 | } 62 | if (methodFound) { 63 | Annotation annotation = method.getAnnotation(OnUiThread.class); 64 | if (annotation != null) { 65 | runOnUiThread(subscriber, method, post); 66 | }else{ 67 | method.setAccessible(true); 68 | method.invoke(subscriber, post.getMessage()); 69 | } 70 | } 71 | return true; 72 | } catch (IllegalAccessException | InvocationTargetException e) { 73 | e.printStackTrace(); 74 | } 75 | } 76 | return false; 77 | } 78 | 79 | private void runOnUiThread(final T subscriber,final Method method,final Post post){ 80 | new Handler(Looper.getMainLooper()).post(new Runnable() { 81 | @Override 82 | public void run() { 83 | try { 84 | method.setAccessible(true); 85 | method.invoke(subscriber, post.getMessage()); 86 | } catch (IllegalAccessException | InvocationTargetException e) { 87 | e.printStackTrace(); 88 | } 89 | } 90 | }); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /java-jpost/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | plugins { 18 | id "com.jfrog.bintray" version "1.7" 19 | } 20 | 21 | def ver = '0.0.4' 22 | def toUpload = false; 23 | 24 | group 'com.mindorks' 25 | version ver 26 | 27 | apply plugin: 'java' 28 | apply plugin: 'idea' 29 | apply plugin: 'maven' 30 | apply plugin: 'maven-publish' 31 | 32 | sourceCompatibility = '1.7' 33 | 34 | task sourcesJar(type: Jar, dependsOn: classes) { 35 | classifier = 'sources' 36 | from sourceSets.main.allSource 37 | } 38 | 39 | task javadocJar(type: Jar, dependsOn: javadoc) { 40 | classifier = 'javadoc' 41 | from javadoc.destinationDir 42 | } 43 | 44 | artifacts { 45 | archives sourcesJar, javadocJar 46 | } 47 | 48 | def pomConfig = { 49 | licenses { 50 | license { 51 | name "The Apache Software License, Version 2.0" 52 | url "http://www.apache.org/licenses/LICENSE-2.0.txt" 53 | distribution "https://github.com/janishar/JPost" 54 | } 55 | } 56 | developers { 57 | developer { 58 | id "janishar.ali@gmail.com" 59 | name "Janishar Ali" 60 | email "janishar.ali@gmail.com" 61 | } 62 | } 63 | } 64 | 65 | publishing { 66 | publications { 67 | MyPublication(MavenPublication) { 68 | from components.java 69 | groupId 'com.mindorks' 70 | artifactId 'java-jpost' 71 | version ver 72 | artifact sourcesJar 73 | artifact javadocJar 74 | pom.withXml { 75 | def root = asNode() 76 | root.appendNode('description', 'java class communication library') 77 | root.children().last() + pomConfig 78 | } 79 | } 80 | } 81 | } 82 | 83 | if(project.rootProject.file("local.properties").exists()){ 84 | Properties properties = new Properties() 85 | properties.load(project.rootProject.file('local.properties').newDataInputStream()) 86 | 87 | bintray { 88 | user = properties.getProperty('bintray.user') 89 | key = properties.getProperty('bintray.apikey') 90 | publications = ['MyPublication'] 91 | dryRun = !toUpload; 92 | pkg { 93 | repo = 'mindorks' 94 | name = 'java-jpost' 95 | licenses = ['Apache-2.0'] 96 | vcsUrl = 'https://github.com/janishar/JPost.git' 97 | labels = ['java', 'communication', 'class', "modular code","pub-sub"] 98 | publicDownloadNumbers = true 99 | version { 100 | name = ver 101 | desc = 'java class communication library' 102 | released = new Date() 103 | vcsTag = ver 104 | attributes = ['java': '1.7'] 105 | } 106 | } 107 | } 108 | } 109 | 110 | repositories { 111 | jcenter() 112 | } 113 | 114 | dependencies { 115 | testCompile group: 'junit', name: 'junit', version: '4.11' 116 | 117 | compile project(':jpost') 118 | // compile 'com.mindorks:jpost:0.0.4' 119 | } 120 | 121 | //UPLOAD PROCEDURE 122 | //cd to the library folder having build.gradle 123 | //ex. cd /Users/janisharali/Mindorks/library/jPost/lib 124 | //gradle bintrayUpload 125 | -------------------------------------------------------------------------------- /android-jpost/src/main/java/com/mindorks/androidjpost/droid/AndroidPrivateChannel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | package com.mindorks.androidjpost.droid; 18 | 19 | import android.os.Handler; 20 | import android.os.Looper; 21 | 22 | import com.mindorks.jpost.core.PrivateChannel; 23 | import com.mindorks.jpost.core.OnMessage; 24 | import com.mindorks.jpost.core.ChannelPost; 25 | import com.mindorks.jpost.core.ChannelState; 26 | import com.mindorks.jpost.core.ChannelType; 27 | import com.mindorks.jpost.core.Post; 28 | 29 | import java.lang.annotation.Annotation; 30 | import java.lang.ref.WeakReference; 31 | import java.lang.reflect.InvocationTargetException; 32 | import java.lang.reflect.Method; 33 | import java.util.concurrent.ConcurrentHashMap; 34 | import java.util.concurrent.PriorityBlockingQueue; 35 | 36 | /** 37 | * Created by janisharali on 22/09/16. 38 | */ 39 | public class AndroidPrivateChannel< 40 | Q extends PriorityBlockingQueue>, 41 | M extends ConcurrentHashMap>> 42 | extends PrivateChannel { 43 | 44 | public AndroidPrivateChannel(Integer channelId, ChannelState state, ChannelType type, Q postQueue, 45 | M subscriberMap, WeakReference channelOwnerRef) { 46 | super(channelId, state, type, postQueue, subscriberMap, channelOwnerRef); 47 | } 48 | 49 | @Override 50 | public > boolean deliverMessage(T subscriber, OnMessage msgAnnotation, Method method, P post) { 51 | int channelId = msgAnnotation.channelId(); 52 | boolean isCommonReceiver = msgAnnotation.isCommonReceiver(); 53 | if (isCommonReceiver || getChannelId().equals(channelId)) { 54 | try { 55 | boolean methodFound = false; 56 | for (final Class paramClass : method.getParameterTypes()) { 57 | if (paramClass.equals(post.getMessage().getClass())) { 58 | methodFound = true; 59 | break; 60 | } 61 | } 62 | if (methodFound) { 63 | Annotation annotation = method.getAnnotation(OnUiThread.class); 64 | if (annotation != null) { 65 | runOnUiThread(subscriber, method, post); 66 | }else{ 67 | method.setAccessible(true); 68 | method.invoke(subscriber, post.getMessage()); 69 | } 70 | } 71 | return true; 72 | } catch (IllegalAccessException | InvocationTargetException e) { 73 | e.printStackTrace(); 74 | } 75 | } 76 | return false; 77 | } 78 | 79 | private void runOnUiThread(final T subscriber,final Method method,final Post post){ 80 | new Handler(Looper.getMainLooper()).post(new Runnable() { 81 | @Override 82 | public void run() { 83 | try { 84 | method.setAccessible(true); 85 | method.invoke(subscriber, post.getMessage()); 86 | } catch (IllegalAccessException | InvocationTargetException e) { 87 | e.printStackTrace(); 88 | } 89 | } 90 | }); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /android-jpost/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | plugins { 18 | id "com.jfrog.bintray" version "1.7" 19 | } 20 | 21 | def ver = '0.0.4' 22 | def toUpload = false; 23 | 24 | group 'com.mindorks' 25 | version ver 26 | 27 | apply plugin: 'java' 28 | apply plugin: 'idea' 29 | apply plugin: 'maven' 30 | apply plugin: 'maven-publish' 31 | 32 | sourceCompatibility = '1.7' 33 | 34 | task sourcesJar(type: Jar, dependsOn: classes) { 35 | classifier = 'sources' 36 | from sourceSets.main.allSource 37 | } 38 | 39 | task javadocJar(type: Jar, dependsOn: javadoc) { 40 | classifier = 'javadoc' 41 | from javadoc.destinationDir 42 | } 43 | 44 | artifacts { 45 | archives sourcesJar, javadocJar 46 | } 47 | 48 | def pomConfig = { 49 | licenses { 50 | license { 51 | name "The Apache Software License, Version 2.0" 52 | url "http://www.apache.org/licenses/LICENSE-2.0.txt" 53 | distribution "https://github.com/janishar/JPost" 54 | } 55 | } 56 | developers { 57 | developer { 58 | id "janishar.ali@gmail.com" 59 | name "Janishar Ali" 60 | email "janishar.ali@gmail.com" 61 | } 62 | } 63 | } 64 | 65 | publishing { 66 | publications { 67 | MyPublication(MavenPublication) { 68 | from components.java 69 | groupId 'com.mindorks' 70 | artifactId 'android-jpost' 71 | version ver 72 | artifact sourcesJar 73 | artifact javadocJar 74 | pom.withXml { 75 | def root = asNode() 76 | root.appendNode('description', 'android class communication library') 77 | root.children().last() + pomConfig 78 | } 79 | } 80 | } 81 | } 82 | 83 | if(project.rootProject.file("local.properties").exists()){ 84 | Properties properties = new Properties() 85 | properties.load(project.rootProject.file('local.properties').newDataInputStream()) 86 | 87 | bintray { 88 | user = properties.getProperty('bintray.user') 89 | key = properties.getProperty('bintray.apikey') 90 | publications = ['MyPublication'] 91 | dryRun = !toUpload; 92 | pkg { 93 | repo = 'mindorks' 94 | name = 'android-jpost' 95 | licenses = ['Apache-2.0'] 96 | vcsUrl = 'https://github.com/janishar/JPost.git' 97 | labels = ['android','event','eventbus', 'java', 'communication', 'class', "modular code","pub-sub"] 98 | publicDownloadNumbers = true 99 | version { 100 | name = ver 101 | desc = 'android class communication library' 102 | released = new Date() 103 | vcsTag = ver 104 | attributes = ['java': '1.7'] 105 | } 106 | } 107 | } 108 | } 109 | 110 | repositories { 111 | jcenter() 112 | } 113 | 114 | dependencies { 115 | testCompile group: 'junit', name: 'junit', version: '4.11' 116 | compile 'com.google.android:android:4.1.1.4' 117 | compile 'com.google.android:support-v4:r7' 118 | compile project(':jpost') 119 | 120 | // compileOnly 'com.google.android:android:4.1.1.4' 121 | // compileOnly 'com.google.android:support-v4:r7' 122 | // compile 'com.mindorks:jpost:0.0.4' 123 | 124 | } 125 | 126 | //UPLOAD PROCEDURE 127 | //cd to the library folder having build.gradle 128 | //ex. cd /Users/janisharali/Mindorks/library/jPost/lib 129 | //gradle bintrayUpload 130 | -------------------------------------------------------------------------------- /jpost/src/main/java/com/mindorks/jpost/core/PublicChannel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | package com.mindorks.jpost.core; 18 | 19 | import com.mindorks.jpost.core.OnMessage; 20 | import com.mindorks.jpost.core.*; 21 | import com.mindorks.jpost.core.ChannelPost; 22 | import com.mindorks.jpost.exceptions.IllegalChannelStateException; 23 | import com.mindorks.jpost.exceptions.NullObjectException; 24 | 25 | import java.lang.annotation.Annotation; 26 | import java.lang.ref.WeakReference; 27 | import java.lang.reflect.Method; 28 | import java.util.concurrent.ConcurrentHashMap; 29 | import java.util.concurrent.PriorityBlockingQueue; 30 | 31 | /** 32 | * Created by janisharali on 22/09/16. 33 | */ 34 | public class PublicChannel< 35 | Q extends PriorityBlockingQueue>, 36 | M extends ConcurrentHashMap>> 37 | extends DefaultChannel 38 | implements CustomChannel{ 39 | 40 | public PublicChannel(Integer channelId, ChannelState state, ChannelType type, Q postQueue, M subscriberMap) { 41 | super(channelId, state, type, postQueue, subscriberMap); 42 | } 43 | 44 | @Override 45 | public void terminateChannel() { 46 | super.setChannelState(ChannelState.TERMINATED); 47 | super.getSubscriberMap().clear(); 48 | super.getPostQueue().clear(); 49 | } 50 | 51 | @Override 52 | public void startChannel() { 53 | super.setChannelState(ChannelState.OPEN); 54 | } 55 | 56 | @Override 57 | public void stopChannel() { 58 | super.setChannelState(ChannelState.STOPPED); 59 | } 60 | 61 | @Override 62 | public void broadcast(T msg, Integer... subscriberIds) throws NullObjectException, IllegalChannelStateException { 63 | if(super.getChannelState() != ChannelState.OPEN){ 64 | throw new IllegalChannelStateException("Channel with id " + super.getChannelId() + " is closed"); 65 | } 66 | if(msg == null){ 67 | throw new NullObjectException("message is null"); 68 | } 69 | ChannelPost post = new ChannelPost<>(msg, getChannelId(), Post.PRIORITY_MEDIUM); 70 | getPostQueue().put(new WeakReference<>(post)); 71 | 72 | while (!getPostQueue().isEmpty()) { 73 | WeakReference msgRef = getPostQueue().poll(); 74 | if(msgRef != null) { 75 | ChannelPost mspPost = msgRef.get(); 76 | if (mspPost != null && mspPost.getChannelId() != null) { 77 | if (mspPost.getChannelId().equals(getChannelId())) { 78 | for (Integer subscriberId : subscriberIds) { 79 | if (getSubscriberMap().containsKey(subscriberId)) { 80 | WeakReference subscriberRef = getSubscriberMap().get(subscriberId); 81 | if(subscriberRef != null) { 82 | Object subscriberObj = subscriberRef.get(); 83 | if (subscriberObj != null) { 84 | for (final Method method : subscriberObj.getClass().getDeclaredMethods()) { 85 | Annotation annotation = method.getAnnotation(OnMessage.class); 86 | if (annotation != null) { 87 | deliverMessage(subscriberObj, (OnMessage) annotation, method, mspPost); 88 | } 89 | } 90 | } 91 | } 92 | } 93 | } 94 | } 95 | } 96 | } 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /java-jpost/src/main/java/com/mindorks/javajpost/JPost.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | package com.mindorks.javajpost; 18 | 19 | import com.mindorks.jpost.core.Broadcast; 20 | import com.mindorks.jpost.core.BroadcastCenter; 21 | import com.mindorks.jpost.core.Channel; 22 | import com.mindorks.jpost.core.ChannelPost; 23 | import com.mindorks.jpost.core.ChannelState; 24 | import com.mindorks.jpost.core.ChannelType; 25 | import com.mindorks.jpost.core.DefaultChannel; 26 | 27 | import java.lang.ref.WeakReference; 28 | import java.util.Comparator; 29 | import java.util.concurrent.ConcurrentHashMap; 30 | import java.util.concurrent.ExecutorService; 31 | import java.util.concurrent.Executors; 32 | import java.util.concurrent.PriorityBlockingQueue; 33 | import java.util.concurrent.locks.ReentrantLock; 34 | 35 | /** 36 | * Created by janisharali on 23/09/16. 37 | */ 38 | public class JPost { 39 | 40 | private static ReentrantLock JPostBootLock = new ReentrantLock(); 41 | 42 | private static ConcurrentHashMap>, 43 | ConcurrentHashMap>>> channelMap; 44 | 45 | private static BroadcastCenter broadcastCenter; 46 | 47 | private static DefaultChannel>, 48 | ConcurrentHashMap>> channel; 49 | 50 | private static int threadCount; 51 | private static ExecutorService executorService; 52 | 53 | static { 54 | init(); 55 | } 56 | 57 | private static void init(){ 58 | threadCount = Runtime.getRuntime().availableProcessors() + 1; 59 | executorService = Executors.newFixedThreadPool(threadCount); 60 | channelMap = new ConcurrentHashMap<>(Broadcast.CHANNEL_INITIAL_CAPACITY); 61 | channel = new DefaultChannel>, 62 | ConcurrentHashMap>>( 63 | Channel.DEFAULT_CHANNEL_ID, 64 | ChannelState.OPEN, 65 | ChannelType.DEFAULT, 66 | new PriorityBlockingQueue<>(Channel.MSG_QUEUE_INITIAL_CAPACITY, 67 | new Comparator>() { 68 | @Override 69 | public int compare(WeakReference o1, WeakReference o2) { 70 | ChannelPost post1 = o1.get(); 71 | ChannelPost post2 = o2.get(); 72 | if(post1 != null || post2 != null 73 | || post1.getPriority() != null 74 | || post2.getPriority() != null){ 75 | return post1.getPriority().compareTo(post2.getPriority()); 76 | }else{ 77 | return 0; 78 | } 79 | } 80 | }), 81 | new ConcurrentHashMap>(Channel.SUBSCRIBER_INITIAL_CAPACITY)); 82 | 83 | channelMap.put(Channel.DEFAULT_CHANNEL_ID, channel); 84 | broadcastCenter = new BroadcastCenter(channelMap, executorService); 85 | } 86 | 87 | public static Broadcast getBroadcastCenter(){ 88 | return broadcastCenter; 89 | } 90 | 91 | public static void reboot(){ 92 | JPostBootLock.lock(); 93 | executorService = Executors.newFixedThreadPool(threadCount); 94 | broadcastCenter.setExecutorService(executorService); 95 | JPostBootLock.unlock(); 96 | } 97 | 98 | public static void shutdown(){ 99 | JPostBootLock.lock(); 100 | executorService.shutdown(); 101 | JPostBootLock.unlock(); 102 | } 103 | 104 | public static void haltAndShutdown(){ 105 | JPostBootLock.lock(); 106 | executorService.shutdownNow(); 107 | JPostBootLock.unlock(); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /android-jpost/src/main/java/com/mindorks/androidjpost/JPost.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | package com.mindorks.androidjpost; 18 | 19 | import com.mindorks.androidjpost.droid.AndroidDefaultChannel; 20 | import com.mindorks.jpost.core.Broadcast; 21 | import com.mindorks.jpost.core.Channel; 22 | import com.mindorks.jpost.core.ChannelPost; 23 | import com.mindorks.jpost.core.ChannelState; 24 | import com.mindorks.jpost.core.ChannelType; 25 | import com.mindorks.jpost.core.DefaultChannel; 26 | 27 | import java.lang.ref.WeakReference; 28 | import java.util.Comparator; 29 | import java.util.concurrent.ConcurrentHashMap; 30 | import java.util.concurrent.ExecutorService; 31 | import java.util.concurrent.Executors; 32 | import java.util.concurrent.PriorityBlockingQueue; 33 | import java.util.concurrent.locks.ReentrantLock; 34 | 35 | /** 36 | * Created by janisharali on 23/09/16. 37 | */ 38 | public class JPost{ 39 | 40 | private static ReentrantLock JPostBootLock = new ReentrantLock(); 41 | 42 | private static ConcurrentHashMap>, 43 | ConcurrentHashMap>>> channelMap; 44 | 45 | private static AndroidBroadcastCenter broadcastCenter; 46 | 47 | private static AndroidDefaultChannel>, 48 | ConcurrentHashMap>> channel; 49 | 50 | private static int threadCount; 51 | private static ExecutorService executorService; 52 | 53 | static { 54 | init(); 55 | } 56 | 57 | private static void init(){ 58 | threadCount = Runtime.getRuntime().availableProcessors() + 1; 59 | executorService = Executors.newFixedThreadPool(threadCount); 60 | channelMap = new ConcurrentHashMap<>(Broadcast.CHANNEL_INITIAL_CAPACITY); 61 | channel = new AndroidDefaultChannel>, 62 | ConcurrentHashMap>>( 63 | Channel.DEFAULT_CHANNEL_ID, 64 | ChannelState.OPEN, 65 | ChannelType.DEFAULT, 66 | new PriorityBlockingQueue<>(Channel.MSG_QUEUE_INITIAL_CAPACITY, 67 | new Comparator>() { 68 | @Override 69 | public int compare(WeakReference o1, WeakReference o2) { 70 | ChannelPost post1 = o1.get(); 71 | ChannelPost post2 = o2.get(); 72 | if(post1 != null || post2 != null 73 | || post1.getPriority() != null 74 | || post2.getPriority() != null){ 75 | return post1.getPriority().compareTo(post2.getPriority()); 76 | }else{ 77 | return 0; 78 | } 79 | } 80 | }), 81 | new ConcurrentHashMap>(Channel.SUBSCRIBER_INITIAL_CAPACITY)); 82 | 83 | channelMap.put(Channel.DEFAULT_CHANNEL_ID, channel); 84 | broadcastCenter = new AndroidBroadcastCenter(channelMap, executorService); 85 | } 86 | 87 | public static Broadcast getBroadcastCenter(){ 88 | return broadcastCenter; 89 | } 90 | 91 | public static void reboot(){ 92 | JPostBootLock.lock(); 93 | executorService = Executors.newFixedThreadPool(threadCount); 94 | broadcastCenter.setExecutorService(executorService); 95 | JPostBootLock.unlock(); 96 | } 97 | 98 | public static void shutdown(){ 99 | JPostBootLock.lock(); 100 | executorService.shutdown(); 101 | JPostBootLock.unlock(); 102 | } 103 | 104 | public static void haltAndShutdown(){ 105 | JPostBootLock.lock(); 106 | executorService.shutdownNow(); 107 | JPostBootLock.unlock(); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /jpost/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | plugins { 18 | id "com.jfrog.bintray" version "1.7" 19 | } 20 | 21 | def ver = '0.0.4' 22 | def toUpload = false; 23 | 24 | group 'com.mindorks' 25 | version ver 26 | 27 | apply plugin: 'java' 28 | apply plugin: 'idea' 29 | apply plugin: 'maven' 30 | apply plugin: 'maven-publish' 31 | 32 | sourceCompatibility = '1.7' 33 | 34 | task sourcesJar(type: Jar, dependsOn: classes) { 35 | classifier = 'sources' 36 | from sourceSets.main.allSource 37 | } 38 | 39 | task javadocJar(type: Jar, dependsOn: javadoc) { 40 | classifier = 'javadoc' 41 | from javadoc.destinationDir 42 | } 43 | 44 | artifacts { 45 | archives sourcesJar, javadocJar 46 | } 47 | 48 | def pomConfig = { 49 | licenses { 50 | license { 51 | name "The Apache Software License, Version 2.0" 52 | url "http://www.apache.org/licenses/LICENSE-2.0.txt" 53 | distribution "https://github.com/janishar/JPost" 54 | } 55 | } 56 | developers { 57 | developer { 58 | id "janishar.ali@gmail.com" 59 | name "Janishar Ali" 60 | email "janishar.ali@gmail.com" 61 | } 62 | } 63 | } 64 | 65 | publishing { 66 | publications { 67 | MyPublication(MavenPublication) { 68 | from components.java 69 | groupId 'com.mindorks' 70 | artifactId 'jpost' 71 | version ver 72 | artifact sourcesJar 73 | artifact javadocJar 74 | pom.withXml { 75 | def root = asNode() 76 | root.appendNode('description', 'jpost core library modules') 77 | root.children().last() + pomConfig 78 | } 79 | } 80 | } 81 | } 82 | 83 | if(project.rootProject.file("local.properties").exists()){ 84 | Properties properties = new Properties() 85 | properties.load(project.rootProject.file('local.properties').newDataInputStream()) 86 | 87 | bintray { 88 | user = properties.getProperty('bintray.user') 89 | key = properties.getProperty('bintray.apikey') 90 | publications = ['MyPublication'] 91 | 92 | dryRun = !toUpload //[Default: false] Whether to run this as dry-run, without deploying 93 | // publish = false //[Default: false] Whether version should be auto published after an upload 94 | // override = false //[Default: false] Whether to override version artifacts already published 95 | 96 | pkg { 97 | repo = 'mindorks' 98 | name = 'jpost' 99 | licenses = ['Apache-2.0'] 100 | vcsUrl = 'https://github.com/janishar/JPost.git' 101 | labels = ['java', 'communication', 'class', "modular code","pub-sub"] 102 | publicDownloadNumbers = true 103 | version { 104 | name = ver 105 | desc = 'java class communication library' 106 | released = new Date() 107 | vcsTag = ver 108 | attributes = ['java': '1.7'] 109 | } 110 | // gpg { 111 | // sign = true //Determines whether to GPG sign the files. The default is false 112 | // passphrase = 'passphrase' //Optional. The passphrase for GPG signing' 113 | // } 114 | // mavenCentralSync { 115 | // sync = false //Optional (true by default). Determines whether to sync the version to Maven Central. 116 | // user = user //OSS user token 117 | // password = properties.getProperty('bintray.gpg.password') //OSS user password 118 | // close = '1' //Optional property. By default the staging repository is closed and artifacts are released to Maven Central. You can optionally turn this behaviour off (by puting 0 as value) and release the version manually. 119 | // } 120 | } 121 | } 122 | } 123 | 124 | repositories { 125 | jcenter() 126 | } 127 | 128 | dependencies { 129 | testCompile group: 'junit', name: 'junit', version: '4.11' 130 | } 131 | 132 | //UPLOAD PROCEDURE 133 | //cd to the library folder having build.gradle 134 | //ex. cd /Users/janisharali/Mindorks/library/jPost/lib 135 | //gradle bintrayUpload 136 | -------------------------------------------------------------------------------- /src/main/java/tes/mindorks/jpost/TestDefaultChannel.java: -------------------------------------------------------------------------------- 1 | package tes.mindorks.jpost; 2 | 3 | import com.mindorks.javajpost.JPost; 4 | import com.mindorks.jpost.exceptions.JPostNotRunningException; 5 | 6 | import tes.mindorks.jpost.message.Message1; 7 | import tes.mindorks.jpost.message.Message2; 8 | import tes.mindorks.jpost.subscriber.Subscriber; 9 | import tes.mindorks.jpost.subscriber.SubscriberAsync; 10 | 11 | 12 | /** 13 | * Created by janisharali on 30/09/16. 14 | */ 15 | 16 | public class TestDefaultChannel { 17 | 18 | static Subscriber subscriberA; 19 | static Subscriber subscriberB; 20 | static SubscriberAsync subscriberAsyncA; 21 | static SubscriberAsync subscriberAsyncB; 22 | 23 | public static void test(){ 24 | testSubscriberSubscribeSync(); 25 | testSubscriberBroadcastSync(); 26 | testSubscriberBroadcastAsync(); 27 | testShutdownRestartSync(); 28 | testShutdownRestartAsync(); 29 | testSubscriberSubscribeAsync(); 30 | testRemoveSubscriber(); 31 | } 32 | 33 | private static void testSubscriberSubscribeSync(){ 34 | System.out.println("testSubscriberSubscribeSync"); 35 | subscriberA = new Subscriber('A'); 36 | subscriberB = new Subscriber('B'); 37 | } 38 | 39 | private static void testSubscriberBroadcastSync(){ 40 | System.out.println("testSubscriberBroadcastSync"); 41 | Message1 message1 = new Message1("Default message subscriber async 1"); 42 | Message2 message2 = new Message2("Default message subscriber async 2"); 43 | JPost.getBroadcastCenter().broadcast(message1); 44 | JPost.getBroadcastCenter().broadcast(message2); 45 | } 46 | 47 | private static void testSubscriberBroadcastAsync(){ 48 | 49 | System.out.println("testSubscriberBroadcastAsync"); 50 | Message1 message1 = new Message1("Default message 1 async"); 51 | Message2 message2 = new Message2("Default message 2 async"); 52 | try { 53 | JPost.getBroadcastCenter().broadcastAsync(message1); 54 | }catch (JPostNotRunningException e){ 55 | e.printStackTrace(); 56 | } 57 | try { 58 | JPost.getBroadcastCenter().broadcastAsync(message2); 59 | }catch (JPostNotRunningException e){ 60 | e.printStackTrace(); 61 | } 62 | } 63 | 64 | private static void testShutdownRestartSync(){ 65 | System.out.println("testShutdownRestartSync"); 66 | JPost.shutdown(); 67 | JPost.getBroadcastCenter().broadcast(new Message1("Default message sync 1 after shutdown")); 68 | JPost.getBroadcastCenter().broadcast(new Message2("Default message sync 2 after shutdown")); 69 | JPost.reboot(); 70 | JPost.getBroadcastCenter().broadcast(new Message1("Default message sync 1 after reboot")); 71 | JPost.getBroadcastCenter().broadcast(new Message2("Default message sync 2 after reboot")); 72 | JPost.reboot(); 73 | } 74 | 75 | private static void testShutdownRestartAsync(){ 76 | System.out.println("testShutdownRestartAsync"); 77 | JPost.shutdown(); 78 | try { 79 | JPost.getBroadcastCenter().broadcastAsync(new Message1("Default message async 1 after shutdown")); 80 | }catch (JPostNotRunningException e){ 81 | e.printStackTrace(); 82 | } 83 | 84 | try { 85 | JPost.getBroadcastCenter().broadcastAsync(new Message2("Default message async 2 after shutdown")); 86 | }catch (JPostNotRunningException e){ 87 | e.printStackTrace(); 88 | } 89 | 90 | JPost.reboot(); 91 | 92 | try { 93 | JPost.getBroadcastCenter().broadcastAsync(new Message1("Default message async 1 after reboot")); 94 | }catch (JPostNotRunningException e){ 95 | e.printStackTrace(); 96 | } 97 | 98 | try { 99 | JPost.getBroadcastCenter().broadcastAsync(new Message2("Default message async 2 after reboot")); 100 | }catch (JPostNotRunningException e){ 101 | e.printStackTrace(); 102 | } 103 | } 104 | 105 | private static void testSubscriberSubscribeAsync(){ 106 | System.out.println("testSubscriberSubscribeAsync"); 107 | subscriberAsyncA = new SubscriberAsync('A'); 108 | subscriberAsyncB = new SubscriberAsync('B'); 109 | } 110 | 111 | private static void testRemoveSubscriber(){ 112 | System.out.println("removeSubscriberTest"); 113 | try { 114 | JPost.getBroadcastCenter().removeSubscriber(subscriberA); 115 | }catch (Exception e){ 116 | e.printStackTrace(); 117 | } 118 | 119 | try { 120 | JPost.getBroadcastCenter().removeSubscriber(subscriberB); 121 | }catch (Exception e){ 122 | e.printStackTrace(); 123 | } 124 | 125 | try { 126 | JPost.getBroadcastCenter().removeSubscriber(subscriberAsyncA); 127 | }catch (Exception e){ 128 | e.printStackTrace(); 129 | } 130 | 131 | try { 132 | JPost.getBroadcastCenter().broadcastAsync(new Message1("Default message async 1 after remove subscriber")); 133 | }catch (JPostNotRunningException e){ 134 | e.printStackTrace(); 135 | } 136 | 137 | try { 138 | JPost.getBroadcastCenter().broadcastAsync(new Message2("Default message async 2 after remove subscriber")); 139 | }catch (JPostNotRunningException e){ 140 | e.printStackTrace(); 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn ( ) { 37 | echo "$*" 38 | } 39 | 40 | die ( ) { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /jpost/src/main/java/com/mindorks/jpost/core/DefaultChannel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | package com.mindorks.jpost.core; 18 | 19 | import com.mindorks.jpost.exceptions.AlreadyExistsException; 20 | import com.mindorks.jpost.exceptions.IllegalChannelStateException; 21 | import com.mindorks.jpost.exceptions.InvalidSubscriberException; 22 | import com.mindorks.jpost.exceptions.NullObjectException; 23 | 24 | import java.lang.annotation.Annotation; 25 | import java.lang.ref.WeakReference; 26 | import java.lang.reflect.InvocationTargetException; 27 | import java.lang.reflect.Method; 28 | import java.util.Iterator; 29 | import java.util.concurrent.ConcurrentHashMap; 30 | import java.util.concurrent.PriorityBlockingQueue; 31 | 32 | /** 33 | * Created by janisharali on 22/09/16. 34 | */ 35 | public class DefaultChannel< 36 | Q extends PriorityBlockingQueue>, 37 | M extends ConcurrentHashMap>> 38 | extends AbstractChannel { 39 | 40 | public DefaultChannel(Integer channelId, ChannelState state, ChannelType type, Q postQueue, M subscriberMap) { 41 | super(channelId, state, type, postQueue, subscriberMap); 42 | 43 | } 44 | 45 | @Override 46 | public void broadcast(T msg) throws NullObjectException, IllegalChannelStateException { 47 | if(super.getChannelState() != ChannelState.OPEN){ 48 | throw new IllegalChannelStateException("Channel with id " + super.getChannelId() + " is closed"); 49 | } 50 | if(msg == null){ 51 | throw new NullObjectException("message is null"); 52 | } 53 | ChannelPost post = new ChannelPost<>(msg, getChannelId(), Post.PRIORITY_MEDIUM); 54 | getPostQueue().put(new WeakReference(post)); 55 | 56 | while (!getPostQueue().isEmpty()) { 57 | WeakReference msgRef = getPostQueue().poll(); 58 | if (msgRef != null) { 59 | ChannelPost mspPost = msgRef.get(); 60 | if (mspPost != null && mspPost.getChannelId() != null) { 61 | if (mspPost.getChannelId().equals(getChannelId())) { 62 | Iterator> iterator = getSubscriberMap().values().iterator(); 63 | while (iterator.hasNext()) { 64 | WeakReference weakReference = iterator.next(); 65 | Object subscriberObj = weakReference.get(); 66 | if (subscriberObj != null) { 67 | for (final Method method : subscriberObj.getClass().getDeclaredMethods()) { 68 | Annotation annotation = method.getAnnotation(OnMessage.class); 69 | if (annotation != null) { 70 | deliverMessage(subscriberObj, (OnMessage) annotation, method, mspPost); 71 | } 72 | } 73 | }else{ 74 | getSubscriberMap().values().remove(weakReference); 75 | } 76 | } 77 | } 78 | } 79 | } 80 | } 81 | } 82 | 83 | @Override 84 | public > boolean deliverMessage(T subscriber, OnMessage msgAnnotation, Method method, P post) { 85 | int channelId = msgAnnotation.channelId(); 86 | boolean isCommonReceiver = msgAnnotation.isCommonReceiver(); 87 | if (isCommonReceiver || getChannelId().equals(channelId)) { 88 | try { 89 | boolean methodFound = false; 90 | for (final Class paramClass : method.getParameterTypes()) { 91 | if (paramClass.equals(post.getMessage().getClass())) { 92 | methodFound = true; 93 | break; 94 | } 95 | } 96 | if (methodFound) { 97 | method.setAccessible(true); 98 | method.invoke(subscriber, post.getMessage()); 99 | } 100 | return true; 101 | } catch (IllegalAccessException | InvocationTargetException e) { 102 | e.printStackTrace(); 103 | } 104 | } 105 | return false; 106 | } 107 | 108 | @Override 109 | public T addSubscriber(T subscriber, Integer subscriberId ) 110 | throws NullObjectException, AlreadyExistsException, IllegalChannelStateException { 111 | if(super.getChannelState() != ChannelState.OPEN){ 112 | throw new IllegalChannelStateException("Channel with id " + super.getChannelId() + " is closed"); 113 | } 114 | if(subscriber == null){ 115 | throw new NullObjectException("subscriber is null"); 116 | } 117 | if(subscriberId == null){ 118 | throw new NullObjectException("subscriberId is null"); 119 | } 120 | if(super.getSubscriberMap().containsKey(subscriberId)){ 121 | throw new AlreadyExistsException("subscriber with subscriberId " + subscriberId + " already registered"); 122 | } 123 | super.getSubscriberMap().put(subscriberId, new WeakReference(subscriber)); 124 | return subscriber; 125 | } 126 | 127 | @Override 128 | public synchronized void removeSubscriber(T subscriber) throws NullObjectException, InvalidSubscriberException { 129 | if(subscriber == null){ 130 | throw new NullObjectException("subscriber is null"); 131 | } 132 | boolean isRemoved = false; 133 | Iterator> iterator = getSubscriberMap().values().iterator(); 134 | while (iterator.hasNext()){ 135 | WeakReference weakReference = iterator.next(); 136 | Object subscriberObj = weakReference.get(); 137 | if(subscriberObj != null && subscriberObj == subscriber){ 138 | getSubscriberMap().values().remove(weakReference); 139 | isRemoved = true; 140 | break; 141 | } 142 | } 143 | if(!isRemoved){ 144 | throw new InvalidSubscriberException("Subscriber do not exists"); 145 | } 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /jpost/src/main/java/com/mindorks/jpost/core/BroadcastCenter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | package com.mindorks.jpost.core; 18 | 19 | import com.mindorks.jpost.core.*; 20 | import com.mindorks.jpost.exceptions.*; 21 | import com.mindorks.jpost.exceptions.IllegalChannelStateException; 22 | 23 | import java.lang.ref.WeakReference; 24 | import java.util.Comparator; 25 | import java.util.concurrent.ConcurrentHashMap; 26 | import java.util.concurrent.ExecutorService; 27 | import java.util.concurrent.PriorityBlockingQueue; 28 | 29 | /** 30 | * Created by janisharali on 22/09/16. 31 | */ 32 | public class BroadcastCenter extends AbstractBroadcastCenter{ 33 | 34 | public BroadcastCenter( 35 | ConcurrentHashMap>, 36 | ConcurrentHashMap>>> channelMap, 37 | ExecutorService executorService) { 38 | super(channelMap, executorService); 39 | } 40 | 41 | @Override 42 | public Channel>, 43 | ConcurrentHashMap>> createPrivateChannel(T owner, Integer channelId) throws AlreadyExistsException { 44 | 45 | if(channelId == null){ 46 | System.out.println("channelId is null"); 47 | return null; 48 | } 49 | if (getChannelMap().containsKey(channelId)) { 50 | throw new AlreadyExistsException("Channel with id " + channelId + " already exists"); 51 | } 52 | 53 | try { 54 | PrivateChannel>, ConcurrentHashMap>> privateChannel = 56 | new PrivateChannel>, 57 | ConcurrentHashMap>>( 58 | channelId, 59 | ChannelState.OPEN, 60 | ChannelType.PRIVATE, 61 | new PriorityBlockingQueue<>(Channel.MSG_QUEUE_INITIAL_CAPACITY, 62 | new Comparator>() { 63 | @Override 64 | public int compare(WeakReference o1, WeakReference o2) { 65 | ChannelPost post1 = o1.get(); 66 | ChannelPost post2 = o2.get(); 67 | if(post1 != null || post2 != null 68 | || post1.getPriority() != null 69 | || post2.getPriority() != null){ 70 | return post1.getPriority().compareTo(post2.getPriority()); 71 | }else{ 72 | return 0; 73 | } 74 | } 75 | }), 76 | new ConcurrentHashMap>(Channel.SUBSCRIBER_INITIAL_CAPACITY), 77 | new WeakReference(owner)); 78 | 79 | getChannelMap().put(channelId, privateChannel); 80 | runPrivateSubscriptionTask(owner, channelId, owner, owner.hashCode()); 81 | return privateChannel; 82 | }catch (IllegalChannelStateException | PermissionException| NullObjectException| NoSuchChannelException e){ 83 | e.printStackTrace(); 84 | } 85 | return null; 86 | } 87 | 88 | @Override 89 | public Channel>, 90 | ConcurrentHashMap>> createPrivateChannel(T owner, Integer channelId, Integer subscriberId) throws AlreadyExistsException{ 91 | if(channelId == null){ 92 | System.out.println("channelId is null"); 93 | return null; 94 | } 95 | if (getChannelMap().containsKey(channelId)) { 96 | throw new AlreadyExistsException("Channel with id " + channelId + " already exists"); 97 | } 98 | 99 | try { 100 | PrivateChannel>, ConcurrentHashMap>> privateChannel = 102 | new PrivateChannel>, 103 | ConcurrentHashMap>>( 104 | channelId, 105 | ChannelState.OPEN, 106 | ChannelType.PRIVATE, 107 | new PriorityBlockingQueue<>(Channel.MSG_QUEUE_INITIAL_CAPACITY, 108 | new Comparator>() { 109 | @Override 110 | public int compare(WeakReference o1, WeakReference o2) { 111 | ChannelPost post1 = o1.get(); 112 | ChannelPost post2 = o2.get(); 113 | if(post1 != null || post2 != null 114 | || post1.getPriority() != null 115 | || post2.getPriority() != null){ 116 | return post1.getPriority().compareTo(post2.getPriority()); 117 | }else{ 118 | return 0; 119 | } 120 | } 121 | }), 122 | new ConcurrentHashMap>(Channel.SUBSCRIBER_INITIAL_CAPACITY), 123 | new WeakReference(owner)); 124 | 125 | getChannelMap().put(channelId, privateChannel); 126 | runPrivateSubscriptionTask(owner, channelId, owner, subscriberId); 127 | return privateChannel; 128 | }catch (IllegalChannelStateException | PermissionException| NullObjectException| NoSuchChannelException e){ 129 | e.printStackTrace(); 130 | } 131 | return null; 132 | } 133 | 134 | @Override 135 | public Channel>, 136 | ConcurrentHashMap>> createPublicChannel(Integer channelId) 137 | throws AlreadyExistsException { 138 | if(channelId == null){ 139 | System.out.println("channelId is null"); 140 | return null; 141 | } 142 | if (getChannelMap().containsKey(channelId)) { 143 | throw new AlreadyExistsException("Channel with id " + channelId + " already exists"); 144 | } 145 | PublicChannel>, ConcurrentHashMap>> publicChannel = 147 | new PublicChannel>, 148 | ConcurrentHashMap>>( 149 | channelId, 150 | ChannelState.OPEN, 151 | ChannelType.PUBLIC, 152 | new PriorityBlockingQueue<>(Channel.MSG_QUEUE_INITIAL_CAPACITY, 153 | new Comparator>() { 154 | @Override 155 | public int compare(WeakReference o1, WeakReference o2) { 156 | ChannelPost post1 = o1.get(); 157 | ChannelPost post2 = o2.get(); 158 | if(post1 != null || post2 != null 159 | || post1.getPriority() != null 160 | || post2.getPriority() != null){ 161 | return post1.getPriority().compareTo(post2.getPriority()); 162 | }else{ 163 | return 0; 164 | } 165 | } 166 | }), 167 | new ConcurrentHashMap>(Channel.SUBSCRIBER_INITIAL_CAPACITY)); 168 | 169 | getChannelMap().put(channelId, publicChannel); 170 | return publicChannel; 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /src/main/java/tes/mindorks/jpost/TestPublicChannel.java: -------------------------------------------------------------------------------- 1 | package tes.mindorks.jpost; 2 | 3 | import com.mindorks.javajpost.JPost; 4 | import com.mindorks.jpost.core.Channel; 5 | import com.mindorks.jpost.exceptions.AlreadyExistsException; 6 | import com.mindorks.jpost.exceptions.JPostNotRunningException; 7 | 8 | import tes.mindorks.jpost.message.Message1; 9 | import tes.mindorks.jpost.message.Message2; 10 | import tes.mindorks.jpost.subscriber.Subscriber; 11 | import tes.mindorks.jpost.subscriber.SubscriberAsync; 12 | 13 | 14 | /** 15 | * Created by janisharali on 30/09/16. 16 | */ 17 | 18 | public class TestPublicChannel { 19 | 20 | static Subscriber subscriberA; 21 | static Subscriber subscriberB; 22 | static SubscriberAsync subscriberAsyncA; 23 | static SubscriberAsync subscriberAsyncB; 24 | 25 | public static void test(){ 26 | createChannel(); 27 | testSubscriberSubscribeSync(); 28 | testSubscriberBroadcastSync(); 29 | testSubscriberBroadcastAsync(); 30 | testShutdownRestartSync(); 31 | testShutdownRestartAsync(); 32 | testSubscriberSubscribeAsync(); 33 | testRemoveSubscriber(); 34 | } 35 | 36 | private static void createChannel(){ 37 | try{ 38 | JPost.getBroadcastCenter().createPublicChannel(ChannelIds.publicChannel1); 39 | }catch (AlreadyExistsException e){ 40 | e.printStackTrace(); 41 | } 42 | } 43 | 44 | private static void testSubscriberSubscribeSync(){ 45 | System.out.println("testSubscriberSubscribeSync"); 46 | subscriberA = new Subscriber('A', ChannelIds.publicChannel1); 47 | subscriberB = new Subscriber('B', ChannelIds.publicChannel1); 48 | } 49 | 50 | private static void testSubscriberBroadcastSync(){ 51 | System.out.println("testSubscriberBroadcastSync"); 52 | Message1 message1 = new Message1("Public message subscriber async 1"); 53 | Message2 message2 = new Message2("Public message subscriber async 2"); 54 | JPost.getBroadcastCenter().broadcast(ChannelIds.publicChannel1, message1); 55 | JPost.getBroadcastCenter().broadcast(ChannelIds.publicChannel1, message2); 56 | } 57 | 58 | private static void testSubscriberBroadcastAsync(){ 59 | 60 | System.out.println("testSubscriberBroadcastAsync"); 61 | Message1 message1 = new Message1("Public message 1 async"); 62 | Message2 message2 = new Message2("Public message 2 async"); 63 | try { 64 | JPost.getBroadcastCenter().broadcastAsync(ChannelIds.publicChannel1, message1); 65 | }catch (JPostNotRunningException e){ 66 | e.printStackTrace(); 67 | } 68 | try { 69 | JPost.getBroadcastCenter().broadcastAsync(ChannelIds.publicChannel1, message2); 70 | }catch (JPostNotRunningException e){ 71 | e.printStackTrace(); 72 | } 73 | } 74 | 75 | private static void testSubscriberBroadcastSelectedSync(){ 76 | System.out.println("testSubscriberBroadcastSync"); 77 | Message1 message1 = new Message1("Public message subscriber async 1"); 78 | Message2 message2 = new Message2("Public message subscriber async 2"); 79 | JPost.getBroadcastCenter().broadcast(ChannelIds.publicChannel1, message1, subscriberA.hashCode()); 80 | JPost.getBroadcastCenter().broadcast(ChannelIds.publicChannel1, message1, 1); 81 | JPost.getBroadcastCenter().broadcast(ChannelIds.publicChannel1, message2, 2); 82 | } 83 | 84 | private static void testSubscriberBroadcastSelectedAsync(){ 85 | 86 | System.out.println("testSubscriberBroadcastAsync"); 87 | Message1 message1 = new Message1("Public message 1 async"); 88 | Message2 message2 = new Message2("Public message 2 async"); 89 | try { 90 | JPost.getBroadcastCenter().broadcastAsync(ChannelIds.publicChannel1, message1, 1, 2); 91 | }catch (JPostNotRunningException e){ 92 | e.printStackTrace(); 93 | } 94 | try { 95 | JPost.getBroadcastCenter().broadcastAsync(ChannelIds.publicChannel1, message2, 1); 96 | }catch (JPostNotRunningException e){ 97 | e.printStackTrace(); 98 | } 99 | } 100 | 101 | private static void testShutdownRestartSync(){ 102 | System.out.println("testShutdownRestartSync"); 103 | JPost.shutdown(); 104 | JPost.getBroadcastCenter().broadcast(ChannelIds.publicChannel1, new Message1("Public message sync 1 after shutdown")); 105 | JPost.getBroadcastCenter().broadcast(new Message2("Public message sync 2 after shutdown")); 106 | JPost.reboot(); 107 | JPost.getBroadcastCenter().broadcast(ChannelIds.publicChannel1, new Message1("Public message sync 1 after reboot")); 108 | JPost.getBroadcastCenter().broadcast(ChannelIds.publicChannel1, new Message2("Public message sync 2 after reboot")); 109 | JPost.reboot(); 110 | } 111 | 112 | private static void testShutdownRestartAsync(){ 113 | System.out.println("testShutdownRestartAsync"); 114 | JPost.shutdown(); 115 | try { 116 | JPost.getBroadcastCenter().broadcastAsync(ChannelIds.publicChannel1, new Message1("Public message async 1 after shutdown")); 117 | }catch (JPostNotRunningException e){ 118 | e.printStackTrace(); 119 | } 120 | 121 | try { 122 | JPost.getBroadcastCenter().broadcastAsync(ChannelIds.publicChannel1, new Message2("Public message async 2 after shutdown")); 123 | }catch (JPostNotRunningException e){ 124 | e.printStackTrace(); 125 | } 126 | 127 | JPost.reboot(); 128 | 129 | try { 130 | JPost.getBroadcastCenter().broadcastAsync(ChannelIds.publicChannel1, new Message1("Public message async 1 after reboot")); 131 | }catch (JPostNotRunningException e){ 132 | e.printStackTrace(); 133 | } 134 | 135 | try { 136 | JPost.getBroadcastCenter().broadcastAsync(ChannelIds.publicChannel1, new Message2("Public message async 2 after reboot")); 137 | }catch (JPostNotRunningException e){ 138 | e.printStackTrace(); 139 | } 140 | } 141 | 142 | private static void testSubscriberSubscribeAsync(){ 143 | System.out.println("testSubscriberSubscribeAsync"); 144 | subscriberAsyncA = new SubscriberAsync('A', ChannelIds.publicChannel1); 145 | subscriberAsyncB = new SubscriberAsync('B', ChannelIds.publicChannel1); 146 | } 147 | 148 | private static void testRemoveSubscriber(){ 149 | System.out.println("removeSubscriberTest"); 150 | try { 151 | JPost.getBroadcastCenter().removeSubscriber(ChannelIds.publicChannel1, subscriberA); 152 | }catch (Exception e){ 153 | e.printStackTrace(); 154 | } 155 | 156 | try { 157 | JPost.getBroadcastCenter().removeSubscriber(ChannelIds.publicChannel1, subscriberB); 158 | }catch (Exception e){ 159 | e.printStackTrace(); 160 | } 161 | 162 | try { 163 | JPost.getBroadcastCenter().removeSubscriber(ChannelIds.publicChannel1, subscriberAsyncA); 164 | }catch (Exception e){ 165 | e.printStackTrace(); 166 | } 167 | 168 | try { 169 | JPost.getBroadcastCenter().broadcastAsync(ChannelIds.publicChannel1, new Message1("Public message async 1 after remove subscriber")); 170 | }catch (JPostNotRunningException e){ 171 | e.printStackTrace(); 172 | } 173 | 174 | try { 175 | JPost.getBroadcastCenter().broadcastAsync(ChannelIds.publicChannel1, new Message2("Public message async 2 after remove subscriber")); 176 | }catch (JPostNotRunningException e){ 177 | e.printStackTrace(); 178 | } 179 | } 180 | 181 | private static void testChannelStateAsync(){ 182 | System.out.println("testChannelStateAsync"); 183 | JPost.getBroadcastCenter().stopChannel(ChannelIds.publicChannel1); 184 | try { 185 | JPost.getBroadcastCenter().broadcastAsync(ChannelIds.publicChannel1, new Message1("Public message async 1 after shutdown")); 186 | }catch (JPostNotRunningException e){ 187 | e.printStackTrace(); 188 | } 189 | 190 | try { 191 | JPost.getBroadcastCenter().broadcastAsync(ChannelIds.publicChannel1, new Message2("Public message async 2 after shutdown")); 192 | }catch (JPostNotRunningException e){ 193 | e.printStackTrace(); 194 | } 195 | 196 | JPost.getBroadcastCenter().reopenChannel(ChannelIds.publicChannel1); 197 | 198 | try { 199 | JPost.getBroadcastCenter().broadcastAsync(ChannelIds.publicChannel1, new Message1("Public message async 1 after reboot")); 200 | }catch (JPostNotRunningException e){ 201 | e.printStackTrace(); 202 | } 203 | 204 | try { 205 | JPost.getBroadcastCenter().broadcastAsync(ChannelIds.publicChannel1, new Message2("Public message async 2 after reboot")); 206 | }catch (JPostNotRunningException e){ 207 | e.printStackTrace(); 208 | } 209 | 210 | JPost.getBroadcastCenter().terminateChannel(ChannelIds.publicChannel1); 211 | 212 | try { 213 | JPost.getBroadcastCenter().broadcastAsync(ChannelIds.publicChannel1, new Message1("Public message async 1 after reboot")); 214 | }catch (JPostNotRunningException e){ 215 | e.printStackTrace(); 216 | } 217 | 218 | try { 219 | JPost.getBroadcastCenter().broadcastAsync(ChannelIds.publicChannel1, new Message2("Public message async 2 after reboot")); 220 | }catch (JPostNotRunningException e){ 221 | e.printStackTrace(); 222 | } 223 | } 224 | } 225 | -------------------------------------------------------------------------------- /android-jpost/src/main/java/com/mindorks/androidjpost/AndroidBroadcastCenter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | package com.mindorks.androidjpost; 18 | 19 | import com.mindorks.androidjpost.droid.AndroidPrivateChannel; 20 | import com.mindorks.androidjpost.droid.AndroidPublicChannel; 21 | import com.mindorks.jpost.core.BroadcastCenter; 22 | import com.mindorks.jpost.core.Channel; 23 | import com.mindorks.jpost.core.ChannelPost; 24 | import com.mindorks.jpost.core.ChannelState; 25 | import com.mindorks.jpost.core.ChannelType; 26 | import com.mindorks.jpost.exceptions.*; 27 | 28 | import java.lang.ref.WeakReference; 29 | import java.util.Comparator; 30 | import java.util.concurrent.ConcurrentHashMap; 31 | import java.util.concurrent.ExecutorService; 32 | import java.util.concurrent.PriorityBlockingQueue; 33 | 34 | 35 | /** 36 | * Created by janisharali on 27/09/16. 37 | */ 38 | public class AndroidBroadcastCenter extends BroadcastCenter { 39 | 40 | public AndroidBroadcastCenter(ConcurrentHashMap>, ConcurrentHashMap>>> channelMap, ExecutorService executorService) { 43 | super(channelMap, executorService); 44 | } 45 | 46 | @Override 47 | public Channel>, ConcurrentHashMap>> createPrivateChannel(T owner, Integer channelId) throws AlreadyExistsException { 49 | if(channelId == null){ 50 | System.out.println("channelId is null"); 51 | return null; 52 | } 53 | if (getChannelMap().containsKey(channelId)) { 54 | throw new AlreadyExistsException("Channel with id " + channelId + " already exists"); 55 | } 56 | 57 | try { 58 | AndroidPrivateChannel>, ConcurrentHashMap>> privateChannel = 60 | new AndroidPrivateChannel>, 61 | ConcurrentHashMap>>( 62 | channelId, 63 | ChannelState.OPEN, 64 | ChannelType.PRIVATE, 65 | new PriorityBlockingQueue<>(Channel.MSG_QUEUE_INITIAL_CAPACITY, 66 | new Comparator>() { 67 | @Override 68 | public int compare(WeakReference o1, WeakReference o2) { 69 | ChannelPost post1 = o1.get(); 70 | ChannelPost post2 = o2.get(); 71 | if(post1 != null || post2 != null 72 | || post1.getPriority() != null 73 | || post2.getPriority() != null){ 74 | return post1.getPriority().compareTo(post2.getPriority()); 75 | }else{ 76 | return 0; 77 | } 78 | } 79 | }), 80 | new ConcurrentHashMap>(Channel.SUBSCRIBER_INITIAL_CAPACITY), 81 | new WeakReference(owner)); 82 | 83 | getChannelMap().put(channelId, privateChannel); 84 | runPrivateSubscriptionTask(owner, channelId, owner, owner.hashCode()); 85 | return privateChannel; 86 | }catch (IllegalChannelStateException | PermissionException| NullObjectException| NoSuchChannelException e){ 87 | e.printStackTrace(); 88 | } 89 | return null; 90 | } 91 | 92 | @Override 93 | public Channel>, ConcurrentHashMap>> createPrivateChannel(T owner, Integer channelId, Integer subscriberId) 95 | throws AlreadyExistsException { 96 | if(channelId == null){ 97 | System.out.println("channelId is null"); 98 | return null; 99 | } 100 | if (getChannelMap().containsKey(channelId)) { 101 | throw new AlreadyExistsException("Channel with id " + channelId + " already exists"); 102 | } 103 | 104 | try { 105 | AndroidPrivateChannel>, ConcurrentHashMap>> privateChannel = 107 | new AndroidPrivateChannel>, 108 | ConcurrentHashMap>>( 109 | channelId, 110 | ChannelState.OPEN, 111 | ChannelType.PRIVATE, 112 | new PriorityBlockingQueue<>(Channel.MSG_QUEUE_INITIAL_CAPACITY, 113 | new Comparator>() { 114 | @Override 115 | public int compare(WeakReference o1, WeakReference o2) { 116 | ChannelPost post1 = o1.get(); 117 | ChannelPost post2 = o2.get(); 118 | if(post1 != null || post2 != null 119 | || post1.getPriority() != null 120 | || post2.getPriority() != null){ 121 | return post1.getPriority().compareTo(post2.getPriority()); 122 | }else{ 123 | return 0; 124 | } 125 | } 126 | }), 127 | new ConcurrentHashMap>(Channel.SUBSCRIBER_INITIAL_CAPACITY), 128 | new WeakReference(owner)); 129 | 130 | getChannelMap().put(channelId, privateChannel); 131 | runPrivateSubscriptionTask(owner, channelId, owner, subscriberId); 132 | return privateChannel; 133 | }catch (IllegalChannelStateException | PermissionException | NullObjectException | NoSuchChannelException e){ 134 | e.printStackTrace(); 135 | } 136 | return null; 137 | } 138 | 139 | @Override 140 | public Channel>, ConcurrentHashMap>> createPublicChannel(Integer channelId) throws AlreadyExistsException { 142 | if(channelId == null){ 143 | System.out.println("channelId is null"); 144 | return null; 145 | } 146 | if (getChannelMap().containsKey(channelId)) { 147 | throw new AlreadyExistsException("Channel with id " + channelId + " already exists"); 148 | } 149 | AndroidPublicChannel>, ConcurrentHashMap>> publicChannel = 151 | new AndroidPublicChannel>, 152 | ConcurrentHashMap>>( 153 | channelId, 154 | ChannelState.OPEN, 155 | ChannelType.PUBLIC, 156 | new PriorityBlockingQueue<>(Channel.MSG_QUEUE_INITIAL_CAPACITY, 157 | new Comparator>() { 158 | @Override 159 | public int compare(WeakReference o1, WeakReference o2) { 160 | ChannelPost post1 = o1.get(); 161 | ChannelPost post2 = o2.get(); 162 | if(post1 != null || post2 != null 163 | || post1.getPriority() != null 164 | || post2.getPriority() != null){ 165 | return post1.getPriority().compareTo(post2.getPriority()); 166 | }else{ 167 | return 0; 168 | } 169 | } 170 | }), 171 | new ConcurrentHashMap>(Channel.SUBSCRIBER_INITIAL_CAPACITY)); 172 | 173 | getChannelMap().put(channelId, publicChannel); 174 | return publicChannel; 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /src/main/java/tes/mindorks/jpost/TestPrivateChannel.java: -------------------------------------------------------------------------------- 1 | package tes.mindorks.jpost; 2 | 3 | import com.mindorks.javajpost.JPost; 4 | import com.mindorks.jpost.exceptions.AlreadyExistsException; 5 | import com.mindorks.jpost.exceptions.JPostNotRunningException; 6 | 7 | import tes.mindorks.jpost.message.Message1; 8 | import tes.mindorks.jpost.message.Message2; 9 | import tes.mindorks.jpost.subscriber.Subscriber; 10 | import tes.mindorks.jpost.subscriber.SubscriberAsync; 11 | 12 | 13 | /** 14 | * Created by janisharali on 30/09/16. 15 | */ 16 | 17 | public class TestPrivateChannel { 18 | 19 | static Subscriber subscriberA; 20 | static Subscriber subscriberB; 21 | static SubscriberAsync subscriberAsyncA; 22 | static SubscriberAsync subscriberAsyncB; 23 | static TestPrivateChannel privateChannelOwner; 24 | 25 | public static void test(){ 26 | privateChannelOwner = new TestPrivateChannel(); 27 | createChannel(); 28 | testSubscriberSubscribeSync(); 29 | testSubscriberBroadcastSync(); 30 | testSubscriberBroadcastAsync(); 31 | testShutdownRestartSync(); 32 | testShutdownRestartAsync(); 33 | testSubscriberSubscribeAsync(); 34 | testRemoveSubscriber(); 35 | } 36 | 37 | private static void createChannel(){ 38 | try{ 39 | JPost.getBroadcastCenter().createPrivateChannel(privateChannelOwner, ChannelIds.privateChannel1); 40 | }catch (AlreadyExistsException e){ 41 | e.printStackTrace(); 42 | } 43 | } 44 | 45 | private static void testSubscriberSubscribeSync(){ 46 | System.out.println("testSubscriberSubscribeSync"); 47 | subscriberA = new Subscriber(privateChannelOwner, 'A', ChannelIds.privateChannel1); 48 | subscriberB = new Subscriber(privateChannelOwner, 'B', ChannelIds.privateChannel1); 49 | } 50 | 51 | private static void testSubscriberBroadcastSync(){ 52 | System.out.println("testSubscriberBroadcastSync"); 53 | Message1 message1 = new Message1("Private message subscriber async 1"); 54 | Message2 message2 = new Message2("Private message subscriber async 2"); 55 | JPost.getBroadcastCenter().broadcast(ChannelIds.privateChannel1, message1); 56 | JPost.getBroadcastCenter().broadcast(ChannelIds.privateChannel1, message2); 57 | } 58 | 59 | private static void testSubscriberBroadcastAsync(){ 60 | 61 | System.out.println("testSubscriberBroadcastAsync"); 62 | Message1 message1 = new Message1("Private message 1 async"); 63 | Message2 message2 = new Message2("Private message 2 async"); 64 | try { 65 | JPost.getBroadcastCenter().broadcastAsync(ChannelIds.privateChannel1, message1); 66 | }catch (JPostNotRunningException e){ 67 | e.printStackTrace(); 68 | } 69 | try { 70 | JPost.getBroadcastCenter().broadcastAsync(ChannelIds.privateChannel1, message2); 71 | }catch (JPostNotRunningException e){ 72 | e.printStackTrace(); 73 | } 74 | } 75 | 76 | private static void testSubscriberBroadcastSelectedSync(){ 77 | System.out.println("testSubscriberBroadcastSync"); 78 | Message1 message1 = new Message1("Private message subscriber async 1"); 79 | Message2 message2 = new Message2("Private message subscriber async 2"); 80 | JPost.getBroadcastCenter().broadcast(privateChannelOwner, ChannelIds.privateChannel1, message1, subscriberA.hashCode()); 81 | JPost.getBroadcastCenter().broadcast(privateChannelOwner, ChannelIds.privateChannel1, message1, 1); 82 | JPost.getBroadcastCenter().broadcast(privateChannelOwner, ChannelIds.privateChannel1, message2, 2); 83 | } 84 | 85 | private static void testSubscriberBroadcastSelectedAsync(){ 86 | 87 | System.out.println("testSubscriberBroadcastAsync"); 88 | Message1 message1 = new Message1("Private message 1 async"); 89 | Message2 message2 = new Message2("Private message 2 async"); 90 | try { 91 | JPost.getBroadcastCenter().broadcastAsync(privateChannelOwner, ChannelIds.privateChannel1, message1, 1, 2); 92 | }catch (JPostNotRunningException e){ 93 | e.printStackTrace(); 94 | } 95 | try { 96 | JPost.getBroadcastCenter().broadcastAsync(privateChannelOwner, ChannelIds.privateChannel1, message2, 1); 97 | }catch (JPostNotRunningException e){ 98 | e.printStackTrace(); 99 | } 100 | } 101 | 102 | private static void testShutdownRestartSync(){ 103 | System.out.println("testShutdownRestartSync"); 104 | JPost.shutdown(); 105 | JPost.getBroadcastCenter().broadcast(privateChannelOwner, ChannelIds.privateChannel1, new Message1("Private message sync 1 after shutdown")); 106 | JPost.getBroadcastCenter().broadcast(privateChannelOwner, ChannelIds.privateChannel1, new Message2("Private message sync 2 after shutdown")); 107 | JPost.reboot(); 108 | JPost.getBroadcastCenter().broadcast(privateChannelOwner, ChannelIds.privateChannel1, new Message1("Private message sync 1 after reboot")); 109 | JPost.getBroadcastCenter().broadcast(privateChannelOwner,ChannelIds.privateChannel1, new Message2("Private message sync 2 after reboot")); 110 | JPost.reboot(); 111 | } 112 | 113 | private static void testShutdownRestartAsync(){ 114 | System.out.println("testShutdownRestartAsync"); 115 | JPost.shutdown(); 116 | try { 117 | JPost.getBroadcastCenter().broadcastAsync(privateChannelOwner, ChannelIds.privateChannel1, new Message1("Private message async 1 after shutdown")); 118 | }catch (JPostNotRunningException e){ 119 | e.printStackTrace(); 120 | } 121 | 122 | try { 123 | JPost.getBroadcastCenter().broadcastAsync(privateChannelOwner, ChannelIds.privateChannel1, new Message2("Private message async 2 after shutdown")); 124 | }catch (JPostNotRunningException e){ 125 | e.printStackTrace(); 126 | } 127 | 128 | JPost.reboot(); 129 | 130 | try { 131 | JPost.getBroadcastCenter().broadcastAsync(privateChannelOwner, ChannelIds.privateChannel1, new Message1("Private message async 1 after reboot")); 132 | }catch (JPostNotRunningException e){ 133 | e.printStackTrace(); 134 | } 135 | 136 | try { 137 | JPost.getBroadcastCenter().broadcastAsync(privateChannelOwner, ChannelIds.privateChannel1, new Message2("Private message async 2 after reboot")); 138 | }catch (JPostNotRunningException e){ 139 | e.printStackTrace(); 140 | } 141 | } 142 | 143 | private static void testSubscriberSubscribeAsync(){ 144 | System.out.println("testSubscriberSubscribeAsync"); 145 | subscriberAsyncA = new SubscriberAsync(privateChannelOwner, 'A', ChannelIds.privateChannel1, 1); 146 | subscriberAsyncB = new SubscriberAsync(privateChannelOwner, 'B', ChannelIds.privateChannel1, 2); 147 | } 148 | 149 | private static void testRemoveSubscriber(){ 150 | System.out.println("removeSubscriberTest"); 151 | try { 152 | JPost.getBroadcastCenter().removeSubscriber(ChannelIds.privateChannel1, subscriberA); 153 | }catch (Exception e){ 154 | e.printStackTrace(); 155 | } 156 | 157 | try { 158 | JPost.getBroadcastCenter().removeSubscriber(ChannelIds.privateChannel1, subscriberB); 159 | }catch (Exception e){ 160 | e.printStackTrace(); 161 | } 162 | 163 | try { 164 | JPost.getBroadcastCenter().removeSubscriber(ChannelIds.privateChannel1, subscriberAsyncA); 165 | }catch (Exception e){ 166 | e.printStackTrace(); 167 | } 168 | 169 | try { 170 | JPost.getBroadcastCenter().broadcastAsync(privateChannelOwner, ChannelIds.privateChannel1, new Message1("Private message async 1 after remove subscriber")); 171 | }catch (JPostNotRunningException e){ 172 | e.printStackTrace(); 173 | } 174 | 175 | try { 176 | JPost.getBroadcastCenter().broadcastAsync(privateChannelOwner, ChannelIds.privateChannel1, new Message2("Private message async 2 after remove subscriber")); 177 | }catch (JPostNotRunningException e){ 178 | e.printStackTrace(); 179 | } 180 | } 181 | 182 | private static void testChannelStateAsync(){ 183 | System.out.println("testChannelStateAsync"); 184 | JPost.getBroadcastCenter().stopChannel(ChannelIds.privateChannel1); 185 | try { 186 | JPost.getBroadcastCenter().broadcastAsync(privateChannelOwner, ChannelIds.privateChannel1, new Message1("Private message async 1 after shutdown")); 187 | }catch (JPostNotRunningException e){ 188 | e.printStackTrace(); 189 | } 190 | 191 | try { 192 | JPost.getBroadcastCenter().broadcastAsync(privateChannelOwner, ChannelIds.privateChannel1, new Message2("Private message async 2 after shutdown")); 193 | }catch (JPostNotRunningException e){ 194 | e.printStackTrace(); 195 | } 196 | 197 | JPost.getBroadcastCenter().reopenChannel(ChannelIds.privateChannel1); 198 | 199 | try { 200 | JPost.getBroadcastCenter().broadcastAsync(privateChannelOwner, ChannelIds.privateChannel1, new Message1("Private message async 1 after reboot")); 201 | }catch (JPostNotRunningException e){ 202 | e.printStackTrace(); 203 | } 204 | 205 | try { 206 | JPost.getBroadcastCenter().broadcastAsync(privateChannelOwner, ChannelIds.privateChannel1, new Message2("Private message async 2 after reboot")); 207 | }catch (JPostNotRunningException e){ 208 | e.printStackTrace(); 209 | } 210 | 211 | JPost.getBroadcastCenter().terminateChannel(ChannelIds.privateChannel1); 212 | 213 | try { 214 | JPost.getBroadcastCenter().broadcastAsync(privateChannelOwner, ChannelIds.privateChannel1, new Message1("Private message async 1 after reboot")); 215 | }catch (JPostNotRunningException e){ 216 | e.printStackTrace(); 217 | } 218 | 219 | try { 220 | JPost.getBroadcastCenter().broadcastAsync(privateChannelOwner, ChannelIds.privateChannel1, new Message2("Private message async 2 after reboot")); 221 | }catch (JPostNotRunningException e){ 222 | e.printStackTrace(); 223 | } 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /jpost/src/main/java/com/mindorks/jpost/core/Broadcast.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | package com.mindorks.jpost.core; 18 | 19 | import com.mindorks.jpost.exceptions.*; 20 | import com.mindorks.jpost.exceptions.IllegalChannelStateException; 21 | 22 | import java.lang.ref.WeakReference; 23 | import java.util.Collection; 24 | import java.util.concurrent.ConcurrentHashMap; 25 | import java.util.concurrent.PriorityBlockingQueue; 26 | 27 | /** 28 | * Created by janisharali on 23/09/16. 29 | */ 30 | public interface Broadcast>, 31 | ? extends ConcurrentHashMap>>> { 32 | 33 | int CHANNEL_INITIAL_CAPACITY = 5; 34 | 35 | /** 36 | * 37 | * @param owner it is the owner of the private channel. 38 | * @param channelId unique int id assigned to the private channel. 39 | * @param object casting to the owner class. 40 | * @return it returns an instance of the created PrivateChannel. 41 | * @throws AlreadyExistsException 42 | */ 43 | C createPrivateChannel(T owner, Integer channelId) throws AlreadyExistsException; 44 | 45 | /** 46 | * 47 | * @param owner it is the owner of the private channel. 48 | * @param channelId unique int id assigned to the private channel. 49 | * @param subscriberId unique int id assigned to the subscriber for the private channel. 50 | * @param object casting to the owner class. 51 | * @return it returns an instance of the created PrivateChannel. 52 | * @throws AlreadyExistsException 53 | */ 54 | C createPrivateChannel(T owner, Integer channelId, Integer subscriberId) throws AlreadyExistsException; 55 | /** 56 | * 57 | * @param channelId unique int id assigned to the public channel. 58 | * @return it returns the instance of the created PublicChannel. 59 | * @throws AlreadyExistsException 60 | */ 61 | C createPublicChannel(Integer channelId) throws AlreadyExistsException; 62 | 63 | /** 64 | * 65 | * @param channelId it stops the public/private channel having channel id equal channelId. 66 | * No message can be send/received through this channel until it is restarted. 67 | */ 68 | void stopChannel(Integer channelId); 69 | 70 | /** 71 | * 72 | * @param channelId it open the channel with channel id. The sending/receiving messages through this channel can resumed. 73 | */ 74 | void reopenChannel(Integer channelId); 75 | 76 | /** 77 | * 78 | * @param channelId it stops the public/private channel having channel id equal channelId. 79 | * No message can be send/received through this channel after termination. 80 | * It removes the channel from the BroadcastCenter. 81 | */ 82 | void terminateChannel(Integer channelId); 83 | 84 | /** 85 | * 86 | * @param channelId unique id identifying a channel. 87 | * @return returns the channel having id as channel id. 88 | * @throws NoSuchChannelException 89 | * @throws NullObjectException 90 | */ 91 | C getChannel(Integer channelId) throws NoSuchChannelException, NullObjectException; 92 | 93 | /** 94 | * 95 | * @param channelId unique id identifying a public channel. 96 | * @param msg any object that has to be send through the public channel. 97 | * @param subscribers the list of specific subscribers subscribed to the public channel that has to be send the message. 98 | * If no subscriber is provided then the message is broadcast to all the subscribers of this channel. 99 | * @param object cast of the msg. 100 | */ 101 | void broadcast(Integer channelId, T msg, Integer... subscribers); 102 | 103 | /** 104 | * 105 | * @param registeredSubscriber it is the owner or the subscriber added to the private channel by th owner. 106 | * @param channelId unique id identifying a private channel. 107 | * @param msg any object that has to be send through the private channel. 108 | * @param subscribers the list of specific subscribers subscribed to the private channel that has to be send the message. 109 | * If no subscriber is provided then the message is broadcast to all the subscribers of this channel. 110 | * @param object cast of the registeredSubscriber. 111 | * @param object cast of the msg. 112 | */ 113 | void broadcast(V registeredSubscriber, Integer channelId, T msg, Integer... subscribers); 114 | 115 | /** 116 | * 117 | * @param msg any object that has to be send through the center global channel. 118 | * It is send to all the subscriber of this channel. 119 | * @param object cast of the msg. 120 | */ 121 | public void broadcast(T msg); 122 | 123 | /** 124 | * 125 | * @param channelId unique id identifying a public channel. 126 | * @param msg any object that has to be send through the public channel asynchronously. 127 | * @param subscribers the list of specific subscribers subscribed to the public channel that has to be send the message. 128 | * If no subscriber is provided then the message is broadcast to all the subscribers of this channel. 129 | * @param object cast of the msg. 130 | */ 131 | void broadcastAsync(Integer channelId, T msg, Integer... subscribers)throws JPostNotRunningException; 132 | 133 | /** 134 | * 135 | * @param registeredSubscriber it is the owner or the subscriber added to the private channel by th owner. 136 | * @param channelId unique id identifying a private channel. 137 | * @param msg any object that has to be send through the private channel. 138 | * @param subscribers the list of specific subscribers subscribed to the private channel that has to be send the message asynchronously. 139 | * If no subscriber is provided then the message is broadcast to all the subscribers of this channel. 140 | * @param object cast of the registeredSubscriber. 141 | * @param object cast of the msg. 142 | */ 143 | void broadcastAsync(V registeredSubscriber, Integer channelId, T msg, Integer... subscribers)throws JPostNotRunningException; 144 | 145 | /** 146 | * 147 | * @param msg any object that has to be send through the center global channel. 148 | * It is send to all the subscriber of this channel asynchronously. 149 | * @param object cast of the msg. 150 | */ 151 | void broadcastAsync(T msg)throws JPostNotRunningException; 152 | 153 | /** 154 | * 155 | * @param channelId unique id identifying a public channel. 156 | * @param subscriber subscriber that is subscribing to the public channel. 157 | * the subscriber is provided subscriber.hashCode() as the subscriber id. 158 | * @param object cast of the subscriber. 159 | * @throws NoSuchChannelException 160 | * @throws AlreadyExistsException 161 | * @throws PermissionException 162 | * @throws IllegalChannelStateException 163 | * @throws NullObjectException 164 | */ 165 | void addSubscriber(Integer channelId, T subscriber) 166 | throws NoSuchChannelException, AlreadyExistsException, PermissionException, IllegalChannelStateException, NullObjectException; 167 | 168 | /** 169 | * 170 | * @param owner the creator of the private channel. 171 | * @param channelId unique id identifying a public channel. 172 | * @param subscriber subscriber that is subscribing to the private channel. 173 | * the subscriber is provided subscriber.hashCode() as the subscriber id. 174 | * @param object cast of the subscriber. 175 | * @param object cast of the owner. 176 | * @throws NoSuchChannelException 177 | * @throws AlreadyExistsException 178 | * @throws PermissionException 179 | * @throws IllegalChannelStateException 180 | * @throws NullObjectException 181 | */ 182 | void addSubscriber(V owner, Integer channelId, T subscriber) 183 | throws NoSuchChannelException, AlreadyExistsException, PermissionException, IllegalChannelStateException, NullObjectException; 184 | 185 | /** 186 | * 187 | * @param channelId unique id identifying a public channel. 188 | * @param subscriber subscriber that is subscribing to the public channel. 189 | * @param subscriberId the subscriber is provided subscriberId as the subscriber id. 190 | * @param object cast of the subscriber. 191 | * @throws NoSuchChannelException 192 | * @throws AlreadyExistsException 193 | * @throws PermissionException 194 | * @throws IllegalChannelStateException 195 | * @throws NullObjectException 196 | */ 197 | void addSubscriber(Integer channelId, T subscriber, Integer subscriberId) 198 | throws NoSuchChannelException, AlreadyExistsException, PermissionException, IllegalChannelStateException, NullObjectException; 199 | 200 | /** 201 | * 202 | * @param owner the creator of the private channel. 203 | * @param channelId unique id identifying a private channel. 204 | * @param subscriber subscriber that is subscribing to the private channel. 205 | * @param subscriberId the subscriber is provided subscriberId as the subscriber id. 206 | * @param object cast of the subscriber. 207 | * @param object cast of the owner. 208 | * @throws NoSuchChannelException 209 | * @throws AlreadyExistsException 210 | * @throws PermissionException 211 | * @throws IllegalChannelStateException 212 | * @throws NullObjectException 213 | */ 214 | void addSubscriber(V owner, Integer channelId, T subscriber, Integer subscriberId) 215 | throws NoSuchChannelException, AlreadyExistsException, PermissionException, IllegalChannelStateException, NullObjectException; 216 | 217 | /** 218 | * 219 | * @param subscriber subscriber that is subscribing to the center global channel. 220 | * the subscriber is provided subscriber.hashCode() as the subscriber id. 221 | * @param object cast of the subscriber. 222 | * @throws AlreadyExistsException 223 | * @throws NullObjectException 224 | */ 225 | void addSubscriber(T subscriber) throws AlreadyExistsException, NullObjectException; 226 | 227 | /** 228 | * 229 | * @param channelId unique id identifying a public channel. 230 | * @param subscriber subscriber that is subscribing to the public channel. 231 | * the subscriber is provided subscriber.hashCode() as the subscriber id. 232 | * @param object cast of the subscriber. 233 | */ 234 | void addSubscriberAsync(Integer channelId, T subscriber); 235 | 236 | /** 237 | * 238 | * @param owner object cast of the owner. 239 | * @param channelId unique id identifying a private channel. 240 | * @param subscriber subscriber that is subscribing to the private channel. 241 | * the subscriber is provided subscriber.hashCode() as the subscriber id. 242 | * @param object cast of the subscriber. 243 | * @param object cast of the owner. 244 | */ 245 | void addSubscriberAsync(V owner, Integer channelId, T subscriber); 246 | 247 | /** 248 | * 249 | * @param channelId unique id identifying a public channel. 250 | * @param subscriber subscriber that is subscribing to the public channel. 251 | * the subscriber is provided subscriberId as the subscriber id. 252 | * @param subscriberId the subscriber is provided subscriberId as the subscriber id. 253 | * @param object cast of the subscriber. 254 | */ 255 | void addSubscriberAsync(Integer channelId, T subscriber, Integer subscriberId); 256 | 257 | /** 258 | * 259 | * @param owner 260 | * @param channelId 261 | * @param subscriber 262 | * @param subscriberId 263 | * @param 264 | * @param 265 | */ 266 | void addSubscriberAsync(V owner, Integer channelId, T subscriber, Integer subscriberId); 267 | 268 | /** 269 | * 270 | * @param subscriber 271 | * @param 272 | */ 273 | void addSubscriberAsync(T subscriber); 274 | 275 | /** 276 | * 277 | * @param subscriber 278 | * @param 279 | * @throws InvalidSubscriberException 280 | * @throws NoSuchChannelException 281 | * @throws NullObjectException 282 | */ 283 | void removeSubscriber(T subscriber) 284 | throws InvalidSubscriberException, NoSuchChannelException, NullObjectException; 285 | 286 | /** 287 | * 288 | * @param channelId 289 | * @param subscriber 290 | * @param 291 | * @throws InvalidSubscriberException 292 | * @throws NoSuchChannelException 293 | * @throws NullObjectException 294 | */ 295 | void removeSubscriber(Integer channelId, T subscriber) 296 | throws InvalidSubscriberException, NoSuchChannelException, NullObjectException; 297 | 298 | /** 299 | * 300 | * @param registeredSubscriber 301 | * @param channelId 302 | * @param subscriberId 303 | * @param 304 | * @throws InvalidSubscriberException 305 | * @throws NoSuchChannelException 306 | * @throws PermissionException 307 | * @throws NullObjectException 308 | */ 309 | void removeSubscriber(T registeredSubscriber, Integer channelId, Integer subscriberId) 310 | throws InvalidSubscriberException, NoSuchChannelException, PermissionException, NullObjectException; 311 | 312 | /** 313 | * 314 | * @param channelId 315 | * @return 316 | * @throws NoSuchChannelException 317 | */ 318 | Collection> getAllSubscribersWeakRef(Integer channelId) throws NoSuchChannelException; 319 | } 320 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JPost (Java and Android class communication library) 2 | [![Build Status](https://travis-ci.org/janishar/JPost.svg?branch=master)](https://travis-ci.org/janishar/JPost) 3 | [ ![Download](https://api.bintray.com/packages/janishar/mindorks/jpost/images/download.svg) ](https://bintray.com/janishar/mindorks/jpost/_latestVersion) 4 | [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-JPost-brightgreen.svg?style=flat)](http://android-arsenal.com/details/1/4432) 5 | [![Mindorks](https://img.shields.io/badge/mindorks-jpost-blue.svg)](https://mindorks.com/open-source-projects) 6 | [![Open Source Love](https://badges.frapsoft.com/os/v1/open-source.svg?v=102)](https://opensource.org/licenses/Apache-2.0) 7 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) 8 | 9 | # Intro 10 | ### This library is designed for the communication between classes in java / android by sending and receiving messages. Messages can be any object. 11 | The design of this library is such that the modularity of the code is enhanced and provide a controlled system for sending and receiving messages. One of the key advantages of this library is that the message handling can be done both synchronusly(if the sender thread is same as the receiver thread) or asynchronously as provided. All the subscribing classes are holded with weakreferences, hense the memory leak do not take place. The usecases in which this library's power can be understood is when compared to other pub/sub libraries. Situations in which many instances of a single class require to process messages based on the sender. Example: A class wants to send message to few of the instances of the same class. The schema diagram provided below will provide a better insight. 12 |
13 | 14 | # Library Design Overview 15 | ### The channels through which communication can be done is categorised into three categories: 16 | 1. **Default Channel**: This is the prebuilt channel and allows global communication. When subscribed to this channel, the class can send messages to all the subscribed classes with message type, on this channel. 17 | 2. **Public Channel**: This channel is designed for filtered communication. Public channels are created and the subscribers of this channel can receive messages broadcasted to this channel. The messages can also be send to selected subscribes. 18 | 3. **Private Channel**: This channel is designed to control the access to the channel. The private channels need to be created and stores the owner information. Only the owner can add new subscribers. The messages can be interchanged between any combination of the added subscribers. 19 | 20 |
21 |
22 |

23 | 24 |

Communication Model

25 |

26 |
27 |
28 |

29 | 30 |

Execution Model

31 |

32 |
33 |
34 |
35 | 36 | # About The Author 37 | You can connect with me here: 38 | * [Janishar Ali](https://janisharali.com) 39 | * [Twitter](https://twitter.com/janisharali) 40 | * [YouTube Channel](https://www.youtube.com/@unusualcode) 41 | 42 | ## If this library helps you in anyway, show your love :heart: by putting a :star: on this project :v: 43 | 44 | # Gradle 45 | # Java 46 | ```groovy 47 | dependencies { 48 | compile 'com.mindorks:java-jpost:0.0.4' 49 | } 50 | ``` 51 | # Android 52 | ```groovy 53 | dependencies { 54 | compile 'com.mindorks:android-jpost:0.0.4' 55 | } 56 | ``` 57 | 58 | # Why should you use this library 59 | 1. In contrast to the existing pub-sub libraries, it hold the subscribers with weakreference. Thus it doesn't create memory leaks. 60 | 2. Single message can be sent to selected subscribes. This avoids the problem of event getting received at undesirable places. Thus minimising the chances of abnormal application behaviour. 61 | 3. The subscriber addition can be controlled by using private channels. It minimises the chances of adding subscribes by mistake to receive undesirable messages. 62 | 4. It is a tiny library < 55kb . Thus not effecting the application overall size. 63 | 5. It facilitates synchronous as well as asynchronous message delivery and processing. 64 | 6. It provides a mechanism to run code asynchronously. 65 | 66 | # Library Classes Overview 67 | # `JPost` 68 | ### The one point entry for this library is the class `JPost`. It contains static methods to access `BroadcastCenter` class and core functionality related to the library management. 69 | ## Methods 70 | 1. `JPost.getBroadcastCenter()`: This method is used to get the instance of BroadcastCenter class (BroadcastCenter is described below) 71 | 2. `JPost.shutdown()`: This method closes the `JPost` for the async operations and removes all the pool threads. It should called when the program terminates or as required. This call let the message delivery already in process to continue. 72 | 3. `JPost.haltAndShutdown()`: This method does the same operation as do the `JPost.shutdown()` but it also removes all the message delivery tasks.; 73 | 74 |
75 | 76 | # `BroadcastCenter` 77 | ### This class proivdes all the functionality attached with this library. 78 | ## Methods 79 | 1. `createPrivateChannel(T owner, Integer channelId)`: Creates a private channel requiring a unique int channel id. The owner is assigned `owner.hashCode()` as subscriber id. 80 | 2. `createPrivateChannel(T owner, Integer channelId, Integer subscriberId)`: Creates a private channel requiring a unique int channel id. The owner is given `subscriberId` as subscriber id. 81 | 3. `createPublicChannel(Integer channelId)`: Creates a public channel requiring a unique int channel id. 82 | 4. `stopChannel(Integer channelId)`: Stops the channel with channel id temporarily. 83 | 5. `reopenChannel(Integer channelId)`: Reopen the channel which has been stopped but not terminated. 84 | 6. `terminateChannel(Integer channelId)`: Completely removes the channel and can not be used later. 85 | 7. `getChannel(Integer channelId)`: Return the channel with channel id else returns null. 86 | 8. `broadcast(T msg)`: This method sends messages to all the subscribers of the default global channel. 87 | 9. `broadcastAsync(T msg)`: This method sends messages asynchronously to all the subscribers of the default global channel. The thread calling this methods can process with remaining tasks as usual. 88 | 10. `broadcast(Integer channelId, T msg, Integer... subscribers)`: This method sends messages to the subscribers of the channel of a particular channel id. If subscribers is not provided then all the subscribers of this channel receiver the message. 89 | 11. `broadcastAsync(Integer channelId, T msg, Integer... subscribers)`: Does the same as above(method 10) but asynchronously. 90 | 12. `broadcast(V registeredSubscriber, Integer channelId, T msg, Integer... subscribers)`: This method is used to send message on a private channel. Only the registered subscribers can send and receive messges on private channel. 91 | 13. `broadcastAsync(V registeredSubscriber, Integer channelId, T msg, Integer... subscribers)`: Does the same as above(method 12) but asynchronously. 92 | 14. `addSubscriber(T subscriber)`: This method add subscribers to default global channel. 93 | 15. `addSubscriber(Integer channelId, T subscriber)`: This method add subscribers to public channels with subscriber having `subscriber.hashCode()` as the subscriber id. 94 | 16. `addSubscriberAsync(Integer channelId, T subscriber)`: Does the same as above(method 15) but asynchronously. 95 | 17. `addSubscriber(Integer channelId, T subscriber, Integer subscriberId)`: This method add subscribers to public channels with subscriber having `subscriberId` as the subscriber id. 96 | 18. `addSubscriberAsync(Integer channelId, T subscriber, Integer subscriberId)`: Does the same as above(method 17) but asynchronously. 97 | 19. `addSubscriber(V owner, Integer channelId, T subscriber)`: This method add subscribers to private channels. Only owner of the channel can add subscribers to this channel. The subscriber is given subscriber.hashCode() as the subscriber id. 98 | 20. `addSubscriberAsync(V owner, Integer channelId, T subscriber)`: Does the same as above(method 19) but asynchronously. 99 | 21. `addSubscriber(V owner, Integer channelId, T subscriber, Integer subscriberId)`: This method add subscribers to private channels. Only owner of the channel can add subscribers to this channel. The subscriber is given `subscriberId` as the subscriber id. 100 | 22. `addSubscriberAsync(V owner, Integer channelId, T subscriber, Integer subscriberId)`: Does the same as above(method 21) but asynchronously. 101 | 23. `removeSubscriber(T subscriber)`: Removes subscriber form the default global channel. 102 | 24. `removeSubscriber(Integer channelId, T subscriber)`: Removes subscriber form a public channel. 103 | 25. `removeSubscriber(T registeredSubscriber, Integer channelId, Integer subscriberId)`: Removes subscriber form a private channel. Only registered subscribers of the private channel can remove a subscriber. 104 | 26. `getAllSubscribersWeakRef()`: returns a collection of weakreference holding the subscriber. 105 | 106 |
107 | 108 | # Receiving Messages 109 | ### The messages are received via `@OnMessage` method annotation. The class subscribing any message has to create a method with message object as the parameter and annotate it with `@OnMessage`. 110 | 111 | ### `@OnMessage` Parameters 112 | 1. `channelId`: This parameter in the annotation, attaches the message reception to a particular channel on which the class has subscribed. If not provided will be listening to the default global channel. 113 | 2. `isCommonReceiver`: This parameter sets the message reception from any channel on which the class has subscribed. 114 | 115 | # Android Note: 116 | ### `@OnUiThread` : This annotation run the code in UI / main thread 117 | ```java 118 | @OnUiThread 119 | @OnMessage 120 | private void onMessage(final Message msg){ 121 | textView.setText(msg.getMsg()); 122 | } 123 | ``` 124 | 125 | # Proguard Note: 126 | ### If you are using proguard, then add this rule in proguard-project.txt 127 | ```groovy 128 | -keepattributes *Annotation* 129 | -keepclassmembers class ** { 130 | @com.mindorks.jpost.core.OnMessage ; 131 | @com.mindorks.androidjpost.droid.OnUiThread ; 132 | } 133 | ``` 134 | 135 | ## Example 1: Sending and receiving messages over default global channel 136 | 137 | ### Step 1: Create a message class that will be passed on the channel for broadcasting. 138 | 139 | ```java 140 | public class Message1 { 141 | 142 | private String msg; 143 | 144 | public Message1(String msg) { 145 | this.msg = msg; 146 | } 147 | 148 | public String getMsg() { 149 | return "Message1: " + msg; 150 | } 151 | 152 | public void setMsg(String msg) { 153 | this.msg = msg; 154 | } 155 | } 156 | ``` 157 | ### Step 2: Subscribe the class to the default global channel 158 | ### Step 3: Attach the message to a recipient class 159 | 160 | ```java 161 | public SubscriberA() { 162 | try { 163 | JPost.getBroadcastCenter().addSubscriber(this); 164 | }catch (AlreadyExistsException | NullObjectException e){ 165 | e.printStackTrace(); 166 | } 167 | } 168 | 169 | @OnMessage 170 | private void onMessage1(Message1 msg){ 171 | System.out.println("SubscriberA: "+ msg.getMsg()); 172 | } 173 | ``` 174 | 175 | ### Step 4: Send the message to the class 176 | ```java 177 | //TO SEND THROUGH THE CLASS RUNNING THREAD USER 178 | JPost.getBroadcastCenter().broadcast(new Message1("Application sending message")); 179 | 180 | // TO SEND ASYNCHRONOUSLY 181 | try { 182 | JPost.getBroadcastCenter().broadcastAsync(new Message2("Application sending message")); 183 | }catch (JPostNotRunningException e){ 184 | e.printStackTrace(); 185 | } 186 | ``` 187 | 188 | ## Example 2: Creating public channel and sending and receiving messages over it 189 | 190 | ### Step 1: Create Message class. This is same as above example 1. 191 | 192 | ### Step 2: Create a public channel and give it a unique id. 193 | 194 | ```java 195 | class ChannelIds{ 196 | public static final int publicChannel1 = 1; 197 | } 198 | 199 | ..... 200 | try { 201 | JPost.getBroadcastCenter().createPublicChannel(ChannelIds.publicChannel1); 202 | }catch (AlreadyExistsException e){ 203 | e.printStackTrace(); 204 | } 205 | ``` 206 | ### Step 3: Subscribe and attach a message recipient to a class 207 | ```java 208 | public SubscriberA() { 209 | // TO ADD SUBSCRIBER SYNCHRONOUSLY 210 | try { 211 | JPost.getBroadcastCenter().addSubscriber(ChannelIds.publicChannel1, this); 212 | }catch (PermissionException | NoSuchChannelException | AlreadyExistsException 213 | | IllegalChannelStateException | NullObjectException e){ 214 | e.printStackTrace(); 215 | } 216 | 217 | ... 218 | // TO ADD SUBSCRIBER ASYNCHRONOUSLY 219 | // JPost.getBroadcastCenter().addSubscriberAsync(ChannelIds.publicChannel1, this); 220 | } 221 | 222 | @OnMessage(channelId = ChannelIds.publicChannel1) 223 | private void onMessage1(Message1 msg){ 224 | System.out.println("SubscriberA: " + msg.getMsg()); 225 | } 226 | ``` 227 | 228 | ### Step 4: Send Message via public channel 229 | ```java 230 | //TO SEND THROUGH THE CLASS RUNNING THREAD USER 231 | JPost.getBroadcastCenter().broadcast(ChannelIds.publicChannel1, new Message1("Application sending public message")); 232 | 233 | // TO SEND ASYNCHRONOUSLY 234 | try { 235 | JPost.getBroadcastCenter().broadcastAsync(ChannelIds.publicChannel1, new Message1("Application sending public async message")); 236 | }catch (JPostNotRunningException e){ 237 | e.printStackTrace(); 238 | } 239 | ``` 240 | 241 | ## Example 3: Creating private channel, adding subscribers(Only creator/owner of the channel has adding subscribers right) and sending and receiving messages over it 242 | ```java 243 | public class ChannelIds { 244 | public static final int privateChannel1 = 2; 245 | } 246 | 247 | // CREATING PRIVATE CHANNEL 248 | try { 249 | JPost.getBroadcastCenter().createPrivateChannel(this, ChannelIds.privateChannel1); 250 | }catch (AlreadyExistsException e){ 251 | e.printStackTrace(); 252 | } 253 | 254 | // ADDING 255 | try { 256 | JPost.getBroadcastCenter().addSubscriber(this, ChannelIds.privateChannel1, subscriberA); 257 | }catch (PermissionException | NoSuchChannelException | AlreadyExistsException 258 | | IllegalChannelStateException | NullObjectException e){ 259 | e.printStackTrace(); 260 | } 261 | 262 | // SUBSCRIBING PRIVATE MESSAGES 263 | @OnMessage(channelId = ChannelIds.privateChannel1) 264 | private void onMessage1(Message1 msg){ 265 | System.out.println("SubscriberD: " + msg.getMsg()); 266 | } 267 | 268 | ``` 269 | 270 | # Interesting Usage 271 | ### 1. The subscribers are added with unique ids. If id is not provided then its hashcode is taken as the id. 272 | ```java 273 | int subscriberId = 1; 274 | try { 275 | JPost.getBroadcastCenter().addSubscriber(ChannelIds.publicChannel1, this, subscriberId); 276 | }catch (PermissionException | NoSuchChannelException | AlreadyExistsException 277 | | IllegalChannelStateException | NullObjectException e){ 278 | e.printStackTrace(); 279 | } 280 | ``` 281 | ### 2. The message can also be send to select subscribers on the channel 282 | ```java 283 | int subscriberId1 = 1; 284 | int subscriberId2 = 2; 285 | try { 286 | JPost.getBroadcastCenter().broadcastAsync(ChannelIds.publicChannel1, 287 | new Message1("Application sending public message"), subscriberId1, subscriberId2); 288 | }catch (JPostNotRunningException e){ 289 | e.printStackTrace(); 290 | } 291 | ``` 292 | # Example 293 | [Android Networking](https://medium.com/@janishar.ali/android-networking-bare-skin-understanding-jpost-5be25f3df4d6#.q21wa4wmy) 294 | 295 | 296 | # Recent Library: [`PlaceHolderView`](https://github.com/janishar/PlaceHolderView) 297 | #### `PlaceHolderView` create views without any adapter in very modular form. It uses the power of RecyclerView and enhances it to another level. For the first time with the list view comes card stack view. 298 | 299 | # License 300 | 301 | ``` 302 | Copyright (C) 2016 Janishar Ali Anwar 303 | 304 | Licensed under the Apache License, Version 2.0 (the "License"); 305 | you may not use this file except in compliance with the License. 306 | You may obtain a copy of the License at 307 | 308 | http://www.apache.org/licenses/LICENSE-2.0 309 | 310 | Unless required by applicable law or agreed to in writing, software 311 | distributed under the License is distributed on an "AS IS" BASIS, 312 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 313 | See the License for the specific language governing permissions and 314 | limitations under the License 315 | 316 | ``` 317 | 318 | 319 | 320 | -------------------------------------------------------------------------------- /jpost/src/main/java/com/mindorks/jpost/core/AbstractBroadcastCenter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Janishar Ali Anwar 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | 17 | package com.mindorks.jpost.core; 18 | 19 | import com.mindorks.jpost.exceptions.*; 20 | 21 | import java.lang.ref.WeakReference; 22 | import java.util.Collection; 23 | import java.util.concurrent.ConcurrentHashMap; 24 | import java.util.concurrent.ExecutorService; 25 | import java.util.concurrent.PriorityBlockingQueue; 26 | import java.util.concurrent.locks.ReentrantLock; 27 | 28 | 29 | /** 30 | * Created by janisharali on 22/09/16. 31 | */ 32 | public abstract class AbstractBroadcastCenter 33 | implements Broadcast>, 34 | ConcurrentHashMap>>>{ 35 | 36 | private ReentrantLock channelStateChangerLock; 37 | private ConcurrentHashMap>, 38 | ConcurrentHashMap>>> channelMap; 39 | private ExecutorService executorService; 40 | 41 | public AbstractBroadcastCenter(ConcurrentHashMap>, 42 | ConcurrentHashMap>>> channelMap, ExecutorService executorService) { 43 | this.channelMap = channelMap; 44 | this.executorService = executorService; 45 | channelStateChangerLock = new ReentrantLock(); 46 | } 47 | 48 | @Override 49 | public void stopChannel(Integer channelId) { 50 | executorService.execute(new ChannelStateTasKRunner(channelId, ChannelState.STOPPED)); 51 | } 52 | 53 | @Override 54 | public void reopenChannel(Integer channelId) { 55 | executorService.execute(new ChannelStateTasKRunner(channelId, ChannelState.OPEN)); 56 | } 57 | 58 | @Override 59 | public void terminateChannel(Integer channelId) { 60 | executorService.execute(new ChannelStateTasKRunner(channelId, ChannelState.TERMINATED)); 61 | } 62 | 63 | @Override 64 | public Channel>, 65 | ConcurrentHashMap>> getChannel(Integer channelId) 66 | throws NoSuchChannelException, NullObjectException { 67 | if(channelId == null){ 68 | throw new NullObjectException("channelId is null"); 69 | } 70 | if(!channelMap.containsKey(channelId)){ 71 | throw new NoSuchChannelException("Channel with id " + channelId + " does not exists"); 72 | } 73 | if(channelMap.get(channelId) == null){ 74 | throw new NoSuchChannelException("Channel with id " + channelId + " does not exists"); 75 | } 76 | return channelMap.get(channelId); 77 | } 78 | 79 | @Override 80 | public void addSubscriber(Integer channelId, T subscriber, Integer subscriberId) 81 | throws NoSuchChannelException, AlreadyExistsException, PermissionException, IllegalChannelStateException, NullObjectException{ 82 | runSubscriptionTask(channelId, subscriber, subscriberId); 83 | } 84 | 85 | @Override 86 | public void addSubscriber(T subscriber) 87 | throws AlreadyExistsException, NullObjectException{ 88 | try { 89 | runSubscriptionTask(Channel.DEFAULT_CHANNEL_ID, subscriber, subscriber.hashCode()); 90 | }catch (NoSuchChannelException | IllegalChannelStateException | PermissionException e){ 91 | e.printStackTrace(); 92 | } 93 | } 94 | 95 | @Override 96 | public void addSubscriber(Integer channelId, T subscriber) 97 | throws NoSuchChannelException, AlreadyExistsException, PermissionException, IllegalChannelStateException, NullObjectException{ 98 | runSubscriptionTask(channelId, subscriber, subscriber.hashCode()); 99 | } 100 | 101 | @Override 102 | public void addSubscriber(V owner, Integer channelId, T subscriber) 103 | throws NoSuchChannelException, AlreadyExistsException, PermissionException, IllegalChannelStateException, NullObjectException{ 104 | runPrivateSubscriptionTask(owner, channelId, subscriber, subscriber.hashCode()); 105 | } 106 | 107 | @Override 108 | public void addSubscriber(V owner, Integer channelId, T subscriber, Integer subscriberId) 109 | throws NoSuchChannelException, AlreadyExistsException, PermissionException, IllegalChannelStateException, NullObjectException{ 110 | runPrivateSubscriptionTask(owner, channelId, subscriber, subscriberId); 111 | } 112 | 113 | @Override 114 | public void addSubscriberAsync(V owner, Integer channelId, T subscriber) { 115 | executorService.execute(new SubscribePrivateTaskRunner<>(owner, channelId, subscriber, subscriber.hashCode())); 116 | } 117 | 118 | @Override 119 | public void addSubscriberAsync(V owner, Integer channelId, T subscriber, Integer subscriberId) { 120 | executorService.execute(new SubscribePrivateTaskRunner<>(owner, channelId, subscriber, subscriberId)); 121 | } 122 | 123 | @Override 124 | public void addSubscriberAsync(Integer channelId, T subscriber, Integer subscriberId) { 125 | executorService.execute(new SubscribeTaskRunner<>(channelId, subscriber, subscriberId)); 126 | } 127 | 128 | @Override 129 | public void addSubscriberAsync(T subscriber) { 130 | executorService.execute(new SubscribeTaskRunner<>(Channel.DEFAULT_CHANNEL_ID, subscriber, subscriber.hashCode())); 131 | } 132 | 133 | @Override 134 | public void addSubscriberAsync(Integer channelId, T subscriber) { 135 | executorService.execute(new SubscribeTaskRunner<>(channelId, subscriber, subscriber.hashCode())); 136 | } 137 | 138 | @Override 139 | public void removeSubscriber(T subscriber) 140 | throws InvalidSubscriberException, NoSuchChannelException, NullObjectException{ 141 | 142 | Channel channel = getChannel(Channel.DEFAULT_CHANNEL_ID); 143 | channel.removeSubscriber(subscriber); 144 | } 145 | 146 | @Override 147 | public void removeSubscriber(Integer channelId, T subscriber) 148 | throws InvalidSubscriberException, NoSuchChannelException, NullObjectException{ 149 | 150 | Channel channel = getChannel(channelId); 151 | channel.removeSubscriber(subscriber); 152 | } 153 | 154 | @Override 155 | public void removeSubscriber(T registeredSubscriber, Integer channelId, Integer subscriberId) 156 | throws InvalidSubscriberException, NoSuchChannelException, PermissionException, NullObjectException{ 157 | 158 | Channel channel = getChannel(channelId); 159 | if(channel instanceof PrivateChannel){ 160 | PrivateChannel privateChannel = (PrivateChannel)channel; 161 | boolean isPermissionGranted = false; 162 | for(Object weakReferenceObj : privateChannel.getSubscriberMap().values()){ 163 | if(weakReferenceObj instanceof WeakReference) { 164 | Object subscriber = ((WeakReference)weakReferenceObj).get(); 165 | if (subscriber != null && subscriber == registeredSubscriber) { 166 | isPermissionGranted = true; 167 | break; 168 | } 169 | } 170 | } 171 | if(isPermissionGranted) { 172 | privateChannel.removeSubscriber(subscriberId); 173 | }else{ 174 | throw new PermissionException("Only the subscriber of the private channel is allowed to broadcast on private channel"); 175 | } 176 | }else{ 177 | throw new NoSuchChannelException("No private channel with channelId " + channelId + " exists"); 178 | } 179 | } 180 | 181 | @Override 182 | public Collection> getAllSubscribersWeakRef(Integer channelId) throws NoSuchChannelException { 183 | try { 184 | Channel>, 185 | ConcurrentHashMap>> channel = getChannel(channelId); 186 | return channel.getAllSubscribersReferenceList(); 187 | }catch (NullObjectException e){ 188 | e.printStackTrace(); 189 | } 190 | return null; 191 | } 192 | 193 | @Override 194 | public void broadcast(T msg){ 195 | try { 196 | runBroadcastTask(Channel.DEFAULT_CHANNEL_ID, msg); 197 | }catch (NoSuchChannelException | NullObjectException | IllegalChannelStateException | PermissionException e){ 198 | e.printStackTrace(); 199 | } 200 | } 201 | 202 | @Override 203 | public void broadcastAsync(T msg) throws JPostNotRunningException{ 204 | if(executorService.isShutdown()){ 205 | throw new JPostNotRunningException("JPost is shutdown"); 206 | } 207 | executorService.execute(new MsgTasKRunner<>(Channel.DEFAULT_CHANNEL_ID, msg)); 208 | } 209 | 210 | @Override 211 | public void broadcast(Integer channelId, T msg, Integer... subscribers){ 212 | try { 213 | runBroadcastTask(channelId, msg, subscribers); 214 | }catch (NoSuchChannelException | NullObjectException | IllegalChannelStateException | PermissionException e){ 215 | e.printStackTrace(); 216 | } 217 | } 218 | 219 | @Override 220 | public void broadcastAsync(Integer channelId, T msg, Integer... subscribers) throws JPostNotRunningException{ 221 | if(executorService.isShutdown()){ 222 | throw new JPostNotRunningException("JPost is shutdown"); 223 | } 224 | executorService.execute(new MsgTasKRunner(channelId, msg, subscribers)); 225 | } 226 | 227 | @Override 228 | public void broadcast(V registeredSubscriber, Integer channelId, T msg, Integer... subscribers){ 229 | try { 230 | runPrivateBroadcastTask(registeredSubscriber, channelId, msg, subscribers); 231 | }catch (NoSuchChannelException | IllegalChannelStateException | PermissionException| NullObjectException e){ 232 | e.printStackTrace(); 233 | } 234 | } 235 | 236 | @Override 237 | public void broadcastAsync(V registeredSubscriber, Integer channelId, T msg, Integer... subscribers) throws JPostNotRunningException{ 238 | if(executorService.isShutdown()){ 239 | throw new JPostNotRunningException("JPost is shutdown"); 240 | } 241 | executorService.execute(new PrivateMsgTasKRunner<>(registeredSubscriber, channelId, msg, subscribers)); 242 | } 243 | 244 | private class ChannelStateTasKRunner implements Runnable{ 245 | 246 | private Integer channelId; 247 | private ChannelState state; 248 | 249 | ChannelStateTasKRunner(Integer channelId, ChannelState state) { 250 | this.channelId = channelId; 251 | this.state = state; 252 | new Thread(this, String.valueOf(channelId)); 253 | } 254 | 255 | @Override 256 | public void run(){ 257 | try { 258 | channelStateChangerLock.lock(); 259 | Channel channel = getChannel(channelId); 260 | if (channel.getChannelState() == ChannelState.TERMINATED) { 261 | throw new IllegalChannelStateException("Channel with id " + channelId + " has been terminated"); 262 | } 263 | if(channel instanceof CustomChannel){ 264 | switch (state){ 265 | case OPEN: 266 | ((CustomChannel)channel).startChannel(); 267 | break; 268 | case STOPPED: 269 | ((CustomChannel)channel).stopChannel(); 270 | break; 271 | case TERMINATED: 272 | ((CustomChannel)channel).terminateChannel(); 273 | channelMap.remove(channelId); 274 | break; 275 | } 276 | } 277 | }catch (NoSuchChannelException | NullObjectException | IllegalChannelStateException e){ 278 | e.printStackTrace(); 279 | }finally { 280 | channelStateChangerLock.unlock(); 281 | } 282 | } 283 | } 284 | 285 | private class MsgTasKRunner implements Runnable{ 286 | 287 | private Integer channelId; 288 | private T msg; 289 | private Integer[] subscribers; 290 | 291 | MsgTasKRunner(Integer channelId, T msg, Integer... subscribers) { 292 | this.channelId = channelId; 293 | this.msg = msg; 294 | this.subscribers = subscribers; 295 | new Thread(this, String.valueOf(channelId)); 296 | } 297 | 298 | @Override 299 | public void run(){ 300 | try{ 301 | runBroadcastTask(channelId, msg, subscribers); 302 | }catch (NoSuchChannelException | NullObjectException | IllegalChannelStateException | PermissionException e){ 303 | e.printStackTrace(); 304 | } 305 | } 306 | } 307 | 308 | private class PrivateMsgTasKRunner implements Runnable{ 309 | 310 | private Integer channelId; 311 | private T msg; 312 | private V registeredSubscriber; 313 | private Integer[] subscribers; 314 | 315 | PrivateMsgTasKRunner(V registeredSubscriber, Integer channelId, T msg, Integer... subscribers) { 316 | this.registeredSubscriber = registeredSubscriber; 317 | this.channelId = channelId; 318 | this.msg = msg; 319 | this.subscribers = subscribers; 320 | new Thread(this, String.valueOf(channelId)); 321 | } 322 | 323 | @Override 324 | public void run(){ 325 | try{ 326 | runPrivateBroadcastTask(registeredSubscriber, channelId, msg, subscribers); 327 | }catch (NoSuchChannelException | NullObjectException | IllegalChannelStateException | PermissionException e){ 328 | e.printStackTrace(); 329 | } 330 | } 331 | } 332 | 333 | private class SubscribeTaskRunner implements Runnable{ 334 | 335 | private Integer channelId; 336 | private Integer subscriberId; 337 | private T subscriber; 338 | 339 | SubscribeTaskRunner(Integer channelId, T subscriber, Integer subscriberId) { 340 | this.channelId = channelId; 341 | this.subscriberId = subscriberId; 342 | this.subscriber = subscriber; 343 | new Thread(this, String.valueOf(channelId)); 344 | } 345 | 346 | @Override 347 | public void run(){ 348 | try { 349 | runSubscriptionTask(channelId, subscriber, subscriberId); 350 | }catch (NoSuchChannelException | NullObjectException | AlreadyExistsException 351 | | IllegalChannelStateException| PermissionException e){ 352 | e.printStackTrace(); 353 | } 354 | } 355 | } 356 | 357 | private class SubscribePrivateTaskRunner implements Runnable{ 358 | 359 | private Integer channelId; 360 | private Integer subscriberId; 361 | private V owner; 362 | private T subscriber; 363 | 364 | SubscribePrivateTaskRunner(V owner, Integer channelId, T subscriber, Integer subscriberId) { 365 | this.owner = owner; 366 | this.channelId = channelId; 367 | this.subscriberId = subscriberId; 368 | this.subscriber = subscriber; 369 | new Thread(this, String.valueOf(channelId)); 370 | } 371 | 372 | @Override 373 | public void run(){ 374 | try { 375 | runPrivateSubscriptionTask(owner, channelId, subscriber, subscriberId); 376 | }catch (NoSuchChannelException | NullObjectException | AlreadyExistsException 377 | | IllegalChannelStateException |PermissionException e){ 378 | e.printStackTrace(); 379 | } 380 | } 381 | } 382 | 383 | private void runBroadcastTask(Integer channelId, T msg, Integer... subscribers) 384 | throws NoSuchChannelException, IllegalChannelStateException, NullObjectException, PermissionException{ 385 | 386 | Channel channel = getChannel(channelId); 387 | if(channel.getChannelState() == ChannelState.OPEN){ 388 | if(channel instanceof PrivateChannel){ 389 | throw new PermissionException("Only subscribers of private channel can send/receive messages over it"); 390 | } 391 | if(channel instanceof PublicChannel && subscribers.length > 0){ 392 | ((PublicChannel)channel).broadcast(msg, subscribers); 393 | }else { 394 | channel.broadcast(msg); 395 | } 396 | }else{ 397 | throw new IllegalChannelStateException("Channel with channelId " + channelId + " has been " + channel.getChannelState()); 398 | } 399 | } 400 | 401 | private void runPrivateBroadcastTask(V registeredSubscriber, Integer channelId, T msg, Integer... subscribers) 402 | throws NoSuchChannelException, PermissionException, IllegalChannelStateException, NullObjectException{ 403 | 404 | Channel channel = getChannel(channelId); 405 | if(channel.getChannelState() == ChannelState.OPEN){ 406 | if(channel instanceof PrivateChannel){ 407 | PrivateChannel privateChannel = (PrivateChannel)channel; 408 | boolean isPermissionGranted = false; 409 | for(Object weakReferenceObj : privateChannel.getSubscriberMap().values()){ 410 | if(weakReferenceObj instanceof WeakReference) { 411 | Object subscriber = ((WeakReference)weakReferenceObj).get(); 412 | if (subscriber != null && subscriber == registeredSubscriber) { 413 | isPermissionGranted = true; 414 | break; 415 | } 416 | } 417 | } 418 | if(isPermissionGranted) { 419 | if(subscribers.length > 0) { 420 | privateChannel.broadcast(msg, subscribers); 421 | }else{ 422 | privateChannel.broadcast(msg); 423 | } 424 | }else{ 425 | throw new PermissionException("Only the subscriber of the private channel is allowed to broadcast on private channel"); 426 | } 427 | }else{ 428 | throw new NoSuchChannelException("No private channel with channelId " + channelId + " exists"); 429 | } 430 | }else{ 431 | throw new IllegalChannelStateException("Channel with channelId " + channelId + " has been " + channel.getChannelState().name()); 432 | } 433 | } 434 | 435 | private void runSubscriptionTask(Integer channelId, T subscriber, Integer subscriberId) 436 | throws NoSuchChannelException, AlreadyExistsException, PermissionException, IllegalChannelStateException, NullObjectException{ 437 | 438 | Channel channel = getChannel(channelId); 439 | if(channel instanceof PrivateChannel){ 440 | throw new PermissionException("Only owner of the private channel can add a subscriber to private channel"); 441 | } 442 | if(channel.getChannelState() == ChannelState.OPEN){ 443 | channel.addSubscriber(subscriber, subscriberId);; 444 | }else{ 445 | throw new IllegalChannelStateException("Channel with channelId " + channelId + " has been " + channel.getChannelState().name()); 446 | } 447 | } 448 | 449 | protected void runPrivateSubscriptionTask(V owner, Integer channelId, T subscriber, Integer subscriberId) 450 | throws NoSuchChannelException, AlreadyExistsException, PermissionException, IllegalChannelStateException, NullObjectException{ 451 | 452 | Channel channel = getChannel(channelId); 453 | if(channel.getChannelState() == ChannelState.OPEN){ 454 | if(channel instanceof PrivateChannel){ 455 | PrivateChannel privateChannel = (PrivateChannel)channel; 456 | if(privateChannel.getChannelOwnerRef() != null){ 457 | Object channelOwner = privateChannel.getChannelOwnerRef().get(); 458 | if(channelOwner != null && channelOwner.equals(owner)) { 459 | privateChannel.addSubscriber(subscriber, subscriberId); 460 | }else{ 461 | throw new PermissionException("Only the owner of the private channel is allowed to add subscribers to private channel"); 462 | } 463 | } 464 | }else{ 465 | throw new NoSuchChannelException("No private channel with channelId " + channelId + " exists"); 466 | } 467 | }else{ 468 | throw new IllegalChannelStateException("Channel with channelId " + channelId + " has been " + channel.getChannelState().name()); 469 | } 470 | } 471 | 472 | protected ConcurrentHashMap>, 473 | ConcurrentHashMap>>> getChannelMap() { 474 | return channelMap; 475 | } 476 | 477 | public ExecutorService getExecutorService() { 478 | return executorService; 479 | } 480 | 481 | public void setExecutorService(ExecutorService executorService) { 482 | this.executorService = executorService; 483 | } 484 | } 485 | --------------------------------------------------------------------------------